Files
summercms/.planning/phases/08-oauth2-1-authorization-server/08-02-PLAN.md
2026-09-23 17:13:47 +02:00

6.7 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
phase plan type wave depends_on files_modified autonomous requirements must_haves
08-oauth2-1-authorization-server 02 execute 2
08-01
../fonoteka.go/plugins/golem15/fonoteka/models/oauth_client.go
../fonoteka.go/plugins/golem15/fonoteka/models/oauth_auth_code.go
../fonoteka.go/plugins/golem15/fonoteka/updates/12_oauth_schema_correction.go
../fonoteka.go/plugins/golem15/fonoteka/updates/oauth_schema_correction_test.go
../fonoteka.go/plugins/golem15/fonoteka/classes/auth/oauth_store.go
../fonoteka.go/plugins/golem15/fonoteka/classes/auth/oauth_store_test.go
true
AUTH-05
AUTH-07
truths artifacts key_links
D-07: Public clients and multiple pending authorization requests persist through one transaction-scoped GORM adapter.
D-17: Expiry sweeps delete only expired lifecycle rows and retain unexpired replay evidence.
path provides
../fonoteka.go/plugins/golem15/fonoteka/updates/12_oauth_schema_correction.go Additive nullability and index correction with safe rollback refusal
path provides
../fonoteka.go/plugins/golem15/fonoteka/classes/auth/oauth_store.go GORM transaction-scoped wristband backend
from to via pattern
oauth_store.go wristband.Backend WithinTx callback whose methods all use callback *gorm.DB WithinTx
Make the existing Postgres schema and app store faithfully represent wristband's client and pending-request state.

Purpose: Separate persistence correctness from protocol and route wiring so nullability, indexes, locking, cap serialization, and sweep semantics are independently verifiable. Output: Corrected models, additive migration, GORM backend, and real-Postgres tests.

<execution_context> @/home/jin/.codex/get-shit-done/workflows/execute-plan.md @/home/jin/.codex/get-shit-done/templates/summary.md </execution_context>

@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/08-oauth2-1-authorization-server/08-CONTEXT.md @.planning/phases/08-oauth2-1-authorization-server/08-RESEARCH.md @.planning/phases/08-oauth2-1-authorization-server/08-01-SUMMARY.md Task 1: Specify schema and store behavior in compiling RED tests ../fonoteka.go/plugins/golem15/fonoteka/updates/oauth_schema_correction_test.go, ../fonoteka.go/plugins/golem15/fonoteka/classes/auth/oauth_store_test.go - Public client secret, pending request id/code hash/user id nullability, named indexes, and rollback refusal are proven on real Postgres. - Two pending requests coexist; atomic cap/sweep/create cannot exceed the configured cap under contention. - Failures emit `PHASE8_RED:persistence` only for absent persistence behavior. D-18: add real-Postgres tests using the existing auth TestMain harness. Compile them against the interfaces from 08-01; use `PHASE8_RED:persistence` assertions for intentionally missing migration/store behavior, and do not use undefined symbols as RED. Include T-08-DCR-FLOOD and transaction-handle tests that detect accidental use of the outer DB. scripts/check-phase8-red.sh persistence bash -lc "cd ../fonoteka.go && go test ./plugins/golem15/fonoteka/classes/auth ./plugins/golem15/fonoteka/updates -run 'TestOAuth(Schema|Store|RegistrationCap)' -count=1" The real-Postgres RED suite compiles, runs named tests, and fails only through the persistence marker. Task 2: Correct OAuth schema and implement the transaction-scoped store ../fonoteka.go/plugins/golem15/fonoteka/models/oauth_client.go, ../fonoteka.go/plugins/golem15/fonoteka/models/oauth_auth_code.go, ../fonoteka.go/plugins/golem15/fonoteka/updates/12_oauth_schema_correction.go, ../fonoteka.go/plugins/golem15/fonoteka/updates/oauth_schema_correction_test.go, ../fonoteka.go/plugins/golem15/fonoteka/classes/auth/oauth_store.go, ../fonoteka.go/plugins/golem15/fonoteka/classes/auth/oauth_store_test.go - Four lifecycle fields are pointers and database nullable; PHP-equivalent operational indexes exist. - Down migration refuses when null lifecycle rows would be lost. - Every store mutation uses the callback transaction and app-tier `FOR UPDATE` where required. D-07: correct `client_secret_hash`, `request_id`, `code_hash`, and `user_id` model fields to pointers and implement the wristband Backend/Tx adapter without importing GORM into wristband. Add a new gormigrate step rather than editing applied history; drop four NOT NULL constraints, create named indexes idempotently, and fail rollback if null rows exist. Implement atomic DCR sweep/cap/create, exact expired-row sweep, and row-lock-capable lifecycle methods using only the callback `*gorm.DB`. D-17: retain unexpired rotated/revoked refresh rows. cd ../fonoteka.go && go test ./plugins/golem15/fonoteka/classes/auth ./plugins/golem15/fonoteka/updates -run 'TestOAuth(Schema|Store|RegistrationCap|Sweep)' -count=1 Postgres can persist public clients and concurrent pending requests, exposes required indexes, serializes DCR cap enforcement, and sweeps only expired rows.

<threat_model>

Trust Boundaries

Boundary Description
wristband records → GORM App-agnostic state crosses into persistent rows and locks.

STRIDE Threat Register

Threat ID Category Component Disposition Mitigation Plan
T-08-DCR-FLOOD Denial of Service client store mitigate Transactionally serialized cap/sweep/create with contention test.
T-08-CODE-REPLAY Spoofing auth-code store mitigate App-tier row-lock methods and single transaction handle.
T-08-REFRESH-REPLAY Spoofing/Elevation refresh store mitigate Preserve replay evidence until expiry and expose locked traversal.
T-08-SC Tampering dependencies mitigate Existing GORM/Postgres only; no install.
</threat_model>
- Focused migration/store Postgres tests pass. - `rg -n 'clause.Locking' ../fonoteka.go/plugins/golem15/fonoteka/classes/auth/oauth_store.go` finds app-tier locks only.

<success_criteria>

  • Schema and store can represent every client/pending/code/refresh lifecycle state.
  • DCR cap and single-use operations have real-Postgres concurrency evidence. </success_criteria>
Create `.planning/phases/08-oauth2-1-authorization-server/08-02-SUMMARY.md` when done.