test(auth): add multi-user regression coverage

- Enable backend tests in CI (remove if: false)
- Fix test_products_helpers.py to pass current_user parameter
- Fix test_routines_helpers.py to include short_id in products
- Fix llm_context.py to use product_effect_profile correctly
- All 221 tests passing
This commit is contained in:
Piotr Oleszczyk 2026-03-12 16:42:00 +01:00
parent b11f64d5a1
commit dac787b81b
45 changed files with 5298 additions and 23 deletions

View file

@ -0,0 +1,13 @@
# T10: Runtime Configuration and Validation
## Learnings
- Nginx needs `X-Forwarded-Host` and `X-Forwarded-Port` for proper OIDC callback URL generation.
- `curl -f` fails on 302 redirects, which are common when a page is protected by OIDC.
- Health checks and deployment scripts must be updated to allow 302/303/307 status codes for the frontend root.
- Bash `((errors++))` returns 1 if `errors` is 0, which can kill the script if `set -e` is active. Use `errors=$((errors + 1))` instead.
- Documenting required environment variables in systemd service files and `DEPLOYMENT.md` is crucial for operators.
- Authelia client configuration requires specific `redirect_uris` and `scopes` (openid, profile, email, groups).
## Verification
- `scripts/validate-env.sh` correctly identifies missing OIDC and session variables.
- `scripts/healthcheck.sh` and `deploy.sh` now handle auth redirects (302) for the frontend.

View file

@ -0,0 +1,5 @@
- Added `users`, `households`, and `household_memberships` tables with OIDC identity key (`oidc_issuer`, `oidc_subject`) and one-household-per-user enforced via unique `household_memberships.user_id`.
- Added `is_household_shared` to `product_inventory` with default `False` so sharing remains per-row opt-in.
- Migration enforces ownership in two phases: nullable + backfill to bootstrap admin, then non-null constraints on all owned tables.
- Correction: migration 4b7d2e9f1c3a applies a two-step ownership rollout (nullable user_id, bootstrap+backfill, then NOT NULL on owned tables).
- Centralized tenant authorization in `innercontext/api/authz.py` and exposed wrappers in `api/utils.py` so routers can move from global `get_or_404` to scoped helpers.

View file

@ -0,0 +1,3 @@
- Full backend pytest currently has pre-existing failures unrelated to this task scope (5 failing tests in routines/skincare helpers after schema changes in this branch context).
- Existing historical migration executes , which breaks full SQLite-from-base upgrades; T2 QA used a synthetic DB pinned at revision to validate the new migration behavior in isolation.
- Correction: historical migration 7c91e4b2af38 runs DROP TYPE IF EXISTS pricetier, which breaks SQLite full-chain upgrades; T2 evidence therefore uses a synthetic DB pinned to revision 9f3a2c1b4d5e for isolated migration validation.

View file

@ -0,0 +1,15 @@
- For ownership rollout without API auth wiring, `user_id` columns can be added as nullable to avoid breaking existing write paths and tests.
- Alembic is needed for SQLite-safe ownership column/FK addition and later non-null enforcement across legacy tables.
- Correction: Alembic batch_alter_table is required for SQLite-safe ownership column/FK addition and non-null enforcement across legacy tables.
- New tenant helpers should keep unauthorized lookups indistinguishable from missing rows by raising `404` with model-not-found detail.
- Product visibility and inventory access are separate checks: household-shared inventory can grant view access without granting update rights.
- Products should be visible when user is owner, admin, or in the same household as at least one household-shared inventory row; inventory payloads must still be filtered to shared rows only for non-owners.
- Shared inventory update rules differ from create/delete: household members in the same household can PATCH shared rows, but POST/DELETE inventory stays owner/admin only.
- Product summary ownership should use Product.user_id (is_owned) rather than active inventory presence, so shared products render as accessible-but-not-owned.
- SvelteKit can keep PKCE server-only by storing the verifier/state in a short-lived encrypted HTTP-only cookie and storing the refreshed app session in a separate encrypted HTTP-only cookie.
- `handleFetch` is enough to attach bearer tokens for server loads/actions that hit `PUBLIC_API_BASE`, but browser-direct `$lib/api` calls to `/api` still need follow-up proxy/auth plumbing outside this task.
- 2026-03-12 T6: Domain routers now enforce per-user ownership by default with explicit `?user_id=` admin override in profile/health/routines/skincare/ai-logs; routine suggestion product pool is constrained to owned+household-shared visibility and uses current user profile context.
- 2026-03-12 T6: QA evidence generated at `.sisyphus/evidence/task-T6-domain-tenancy.txt` and `.sisyphus/evidence/task-T6-routine-scope.txt` with passing scenarios.
- 2026-03-12 T9: Admin household management can stay backend-only by listing synced local `users` plus current membership state, creating bare `households`, and handling assign/move/remove as explicit membership operations.
- 2026-03-12 T9: Unsynced identities should fail assignment via local `User` lookup rather than implicit creation, keeping Authelia as the only identity source and preserving the v1 one-household-per-user rule.
- 2026-03-12 T8: Server-side frontend API helpers should call `PUBLIC_API_BASE` directly with the access token from `event.locals.session`; same-origin SvelteKit endpoints are still the right bridge for browser-only interactions like AI modals and inline PATCHes.

View file

@ -0,0 +1,3 @@
- Pending follow-up migration task is required to materialize new models/columns in PostgreSQL schema.
- End-to-end SQLite from base revision remains blocked by pre-existing non-SQLite-safe migration logic () outside T2 scope.
- Correction: full SQLite alembic upgrade head from base is still blocked by pre-existing DROP TYPE usage in migration 7c91e4b2af38 (outside T2 scope).