Skip to content

Add GET /v1/goals/{goal_id}: fetch a single goal by id#9386

Open
ZachL111 wants to merge 7 commits into
BasedHardware:mainfrom
ZachL111:zach/goal-get-by-id
Open

Add GET /v1/goals/{goal_id}: fetch a single goal by id#9386
ZachL111 wants to merge 7 commits into
BasedHardware:mainfrom
ZachL111:zach/goal-get-by-id

Conversation

@ZachL111

@ZachL111 ZachL111 commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds GET /v1/goals/{goal_id} to fetch a single goal by id.

Motivation

The goals API already lets a client update, delete, set progress on, and read the history and advice of a goal by its id, and lists goals via /v1/goals and /v1/goals/all. But there was no plain read of one goal by id. A client that wants to display or refresh a specific goal (for example after an edit, or when deep-linking to a goal) had to fetch the whole capped list and filter client-side.

Change

  • database/goals.py: get_goal(uid, goal_id) returns the goal dict, or None if it does not exist. It mirrors the read update_goal already does (document(goal_id).get(), then _goal_dict to ensure the id is present).
  • routers/goals.py: GET /v1/goals/{goal_id} returns the normalized goal, or 404 when the goal does not exist or belongs to another user (the lookup is scoped to the caller's own uid). It is declared after the static /v1/goals/* routes (/all, /suggest, /advice, /extract-progress) so those match first and are not captured as a goal_id.

The change is additive and does not touch existing routes.

Testing

  • New tests/unit/test_goal_get_by_id.py: the endpoint returns the normalized goal and returns 404 when the goal is absent; the DB helper returns None for a missing document and fills id from the document id when present.
  • Ran black, py_compile, the async blocker scan, the import-time side-effect scan, and the stub-pollution scan locally; all clean.
  • Verified at the unit level (handler called directly, DB helper against a fake Firestore client). I did not run it against a live backend, since that needs Firestore credentials I do not have locally.

Review in cubic

@Git-on-my-level Git-on-my-level added the docs-accuracy Documentation or committed reports need accuracy fixes label Jul 10, 2026

@Git-on-my-level Git-on-my-level left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the focused addition — the endpoint and DB helper look straightforward, and the new unit coverage matches the intended 404/normalization behavior.

I do need to request one fix before this can merge: the committed app-client OpenAPI contract is stale. I reproduced the failing CI locally with:

cd backend
env -i PATH="$PATH" HOME="$HOME" OPENAPI_RUNNER_VENV="/tmp/omi-pr9386-review/.openapi-venv" \
  ./scripts/openapi_runner.sh scripts/export_openapi.py --surface app-client --check ../docs/api-reference/app-client-openapi.json

which reports:

OpenAPI contract check failed: ../docs/api-reference/app-client-openapi.json is stale; run backend/scripts/export_openapi.py --write ../docs/api-reference/app-client-openapi.json

Please regenerate and commit docs/api-reference/app-client-openapi.json for the new GET /v1/goals/{goal_id} route, then the contract check should be able to go green. I’m not seeing a security/supply-chain concern in the code itself; this is mainly a public API contract artifact issue on an authenticated goal read endpoint.

@ZachL111 ZachL111 force-pushed the zach/goal-get-by-id branch from e07b1e6 to 25ebd33 Compare July 10, 2026 13:58
@ZachL111

Copy link
Copy Markdown
Contributor Author

Done. Regenerated docs/api-reference/app-client-openapi.json with backend/scripts/export_openapi.py --surface app-client --write; the only change is the new GET /v1/goals/{goal_id} operation, and --surface app-client --check passes locally now. Pushed.

@kodjima33 kodjima33 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Backend read endpoint GET /v1/goals/{goal_id}; mirrors existing goal routes. Approve (feature, backend deploy is Nik's).

ZachL111 added 5 commits July 10, 2026 12:36
The goals API already lets a client update, delete, set progress on, and read the
history/advice of a goal by its id, and lists goals via /v1/goals and /v1/goals/all,
but there was no plain read of one goal by id: a client wanting to display or refresh
a specific goal had to page the capped list and filter client-side. Adds
get_goal(uid, goal_id) in the DB layer (mirroring update_goal's read) and the matching
endpoint, returning 404 when the goal does not exist or belongs to another user.
Declared after the static /v1/goals/* routes so those still match first.
…_id}

The Public Developer API contract check flagged docs/api-reference/app-client-openapi.json
as stale after the goal-by-id route was added. Regenerated via
backend/scripts/export_openapi.py --surface app-client --write; the only change is the new
GET /v1/goals/{goal_id} operation.
…r GET /v1/goals/{goal_id}

Adds the route-policy manifest entry (legacy_unreviewed) for the new goal-by-id route and
regenerates the app-client TypeScript and Swift client schemas, so the Public Developer API
contract check passes. Only the new operation is added.
… client

The app-client contract regen for GET /v1/goals/{goal_id} updates the generated Swift and
Windows API client schemas (desktop files), which the desktop changelog Hygiene check requires
a fragment for.
…edHardware#9357

BasedHardware#9357 stopped gating the daily recap on the desktop trial paywall, removing the
is_trial_paywalled call from _send_summary_notification. test_lock_bypass_fixes still
patched utils.other.notifications.is_trial_paywalled, which no longer exists there, so
TestScheduledDailySummaryLockFilter failed with AttributeError on every run (in isolation
and in the full unit suite), redding the Backend unit suite on full-suite PRs. Remove the
vestigial patch; the tests still cover the locked-conversation filter, their actual purpose.
@ZachL111 ZachL111 force-pushed the zach/goal-get-by-id branch from d3253c3 to 9f386f4 Compare July 10, 2026 19:37
ZachL111 added 2 commits July 11, 2026 02:17
# Conflicts:
#	backend/database/goals.py
#	backend/route_policy_manifest.yaml
#	backend/tests/unit/test_lock_bypass_fixes.py
#	desktop/macos/Desktop/Sources/Generated/OmiApi.generated.swift
#	desktop/windows/src/renderer/src/lib/omiApi.generated.ts
#	web/admin/lib/services/omi-api/omiApi.generated.ts
#	web/app/src/lib/omiApi.generated.ts
#	web/personas-open-source/src/lib/omiApi.generated.ts
… _goal_dict

The main merge exposed two issues: (1) get_goal was resolved to _get_db(), which
constructs a live Firestore client the hermetic test blocks (metadata server) since
the test patches database.goals.db; revert get_goal to the db proxy. (2) _goal_dict on
main now fills the goal_id alias, so the db test expectation gains goal_id. Also freeze
wall-clock in the trial-boundary tests (same as BasedHardware#8499) to remove the main-side flake.
@Git-on-my-level Git-on-my-level removed the docs-accuracy Documentation or committed reports need accuracy fixes label Jul 11, 2026
@Git-on-my-level

Copy link
Copy Markdown
Collaborator

Thanks for the follow-up here. I re-reviewed the current head after the OpenAPI/regenerated-client updates.

The previous docs/contract concern looks addressed: docs/api-reference/app-client-openapi.json now includes the new GET /v1/goals/{goal_id} operation, the generated TS/Swift clients include the matching helper, and the Public Developer API contract check is green. I also removed the stale docs-accuracy label.

Implementation-wise, the endpoint is a narrow additive authenticated read scoped through uid, returns 404 for absent/not-owned goals, and the new unit coverage exercises the router happy path, missing-goal behavior, and DB helper _goal_dict id/goal_id filling. I’m not seeing a security or supply-chain concern in the current diff.

Because this still touches an authenticated user-data API surface and there is an existing maintainer changes-requested review on the PR, I’m leaving this as a positive maintainer-ready signal rather than a formal approval. A human maintainer should do the final review/dismissal of the earlier requested-changes state if satisfied.

@ZachL111

Copy link
Copy Markdown
Contributor Author

Thanks for the re-review and for clearing the docs-accuracy label. Agreed the OpenAPI regen resolved the contract check, and nothing else is outstanding from my side. Ready for a maintainer to dismiss the earlier changes-requested state whenever convenient.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants