17fc813823
M1, M2 and M3 complete * M1, M2 and M3 complete * review changes * docs * docs
87 lines
6.1 KiB
Markdown
87 lines
6.1 KiB
Markdown
# Mutable Metadata Plan v3 Review (Codex)
|
||
A review of plans/mutable.metadata.plan.combo.v3.md and plans/mutable.metadata.plan.combo.v3.tracking.md since they are to be used as a pair to implement the plans/mutable.metadata.plan.combo.v3.md plan.
|
||
|
||
|
||
I reviewed the current legacy field-extraction flow first so the plan review is anchored to real behavior:
|
||
|
||
- `api/queryAPI/fieldextractions.go:20-69` binds the request, calls `FieldExtraction.CreateFieldExtraction`, and currently maps any create error to HTTP 500.
|
||
- `internal/fieldextraction/service.go:27-100` creates the extraction row, then locks existing version rows, computes `max(version)+1`, and inserts the version row.
|
||
- Authorization today is checked as `(user, action, first-path-segment resource)` with no document/client object passed into Permit.io: `internal/cognitoauth/middleware.go:84-110`, `internal/cognitoauth/permitio.go:79-89`.
|
||
|
||
## Findings
|
||
|
||
1. **Blocking: the tracking doc’s migration numbers collide with live migrations already in the repo.**
|
||
References:
|
||
- `plans/mutable.metadata.plan.combo.v3.tracking.md:48-75`
|
||
- `internal/database/migrations`: existing `00000000000120_*` through `00000000000123_*` are already present (`00000000000120_remove_text_extraction`, `00000000000121_create_eula_tables`, `00000000000122_make_eula_effective_date_nullable`, `00000000000123_create_ui_settings`)
|
||
Impact:
|
||
- Phase 1 cannot start as written.
|
||
- Any implementation that follows the tracking doc literally will create filename collisions and broken migration ordering.
|
||
Recommendation:
|
||
- Renumber all new mutable-metadata migrations to the next free sequence and update every tracking reference before coding.
|
||
|
||
2. **Blocking: the plan grants `/custom-metadata` read/write to `client_user`, but the current auth model is not tenant-scoped.**
|
||
References:
|
||
- Plan grants: `plans/mutable.metadata.plan.combo.v3.md:730-780`
|
||
- Current auth check: `internal/cognitoauth/middleware.go:105-110`, `internal/cognitoauth/permitio.go:79-89`
|
||
- Current documented limitation: `cmd/auth_related/permit.setup/permit_policies.yaml:155-184`
|
||
Impact:
|
||
- `custom-metadata:get/post` would be authorized purely by resource/action on the first path segment.
|
||
- Without new application-level document/client ownership checks, a `client_user` or `user_admin` who knows another document UUID can read/write that document’s custom metadata across clients.
|
||
Recommendation:
|
||
- Resolve scoping before implementation. Either:
|
||
- Add explicit document/client ownership enforcement in the custom-metadata service/controller and track it as first-class work, or
|
||
- Do not grant `client_user`/`user_admin` write access to `/custom-metadata` until tenant scoping exists.
|
||
|
||
3. **High: Phase 5a in the tracking doc misses the HTTP-layer work needed to return the documented 409.**
|
||
References:
|
||
- Tracking: `plans/mutable.metadata.plan.combo.v3.tracking.md:290-299`
|
||
- Current controller behavior: `api/queryAPI/fieldextractions.go:45-50`
|
||
Impact:
|
||
- Adding only a service pre-check will not produce the promised HTTP 409.
|
||
- As written, `POST /field-extractions` will still return 500 for the new mutual-exclusivity error.
|
||
Recommendation:
|
||
- Add explicit controller error mapping and HTTP tests for the legacy write guard, not just service tests.
|
||
|
||
4. **High: the reset-metadata section is internally inconsistent about documents that already have legacy field extractions.**
|
||
References:
|
||
- `plans/mutable.metadata.plan.combo.v3.md:643-653`
|
||
Impact:
|
||
- The behavior bullets say a legacy-extraction document “succeeds trivially.”
|
||
- The validation section says the same condition returns `409 Conflict`.
|
||
- The tracking doc appears to assume `409`, so the plan and tracker are not actually aligned.
|
||
Recommendation:
|
||
- Pick one behavior and update both docs. I recommend `409`, because it matches the mutual-exclusivity rule and avoids false-success responses on legacy documents.
|
||
|
||
5. **High: the custom-metadata versioning plan overstates its concurrency safety, especially on first write.**
|
||
References:
|
||
- Plan claim: `plans/mutable.metadata.plan.combo.v3.md:152-153`
|
||
- Tracking task: `plans/mutable.metadata.plan.combo.v3.tracking.md:239-245`
|
||
- Current legacy pattern: `internal/fieldextraction/service.go:70-100`
|
||
Impact:
|
||
- `SELECT ... FOR UPDATE` on the max-version row does not serialize the first write for a document, because there is no row to lock yet.
|
||
- Two concurrent first writes can still race and one will fail on `UNIQUE (document_id, version)`.
|
||
Recommendation:
|
||
- Decide on a real serialization strategy now:
|
||
- Lock the document row before version assignment, or
|
||
- Retry on unique-violation explicitly.
|
||
- Add a “concurrent first write” test to the tracker, not just a generic concurrency test.
|
||
|
||
6. **Medium: actor/audit provenance is underspecified and currently inconsistent with the plan’s audit goals.**
|
||
References:
|
||
- Request bodies still carry caller-supplied `createdBy`: `plans/mutable.metadata.plan.combo.v3.md:566-571`, `847-858`
|
||
- Tracking only explicitly extracts caller identity for reset: `plans/mutable.metadata.plan.combo.v3.tracking.md:431-447`, `502`
|
||
- Reset refers to a not-yet-defined “same log sink used by `AssignSchema` / `DeleteSchema`”: `plans/mutable.metadata.plan.combo.v3.md:638`, `1069`
|
||
Impact:
|
||
- If `created_by` is meant to be audit-authoritative, client-supplied JSON is not trustworthy.
|
||
- The tracker does not currently include the work to derive actor identity from auth context for schema create/update/delete, folder assign, or metadata writes.
|
||
- The audit sink itself is assumed rather than designed.
|
||
Recommendation:
|
||
- Decide now whether actor identity is authoritative or merely display metadata.
|
||
- If authoritative, derive it from auth context everywhere and add explicit tracking tasks.
|
||
- Define the concrete audit sink/API instead of leaving it implied.
|
||
|
||
## Bottom Line
|
||
|
||
I would not start implementation until Findings 1 and 2 are resolved. Findings 3 through 6 should be folded into the tracking doc before work starts, otherwise the implementation will either drift from the plan or discover these gaps mid-phase.
|