Files
query-orchestration/plans/mutable.metadata.review.combo.v3.codex.md
T
Jay Brown 17fc813823 Merged in feature/mutable-metadata1 (pull request #221)
M1, M2 and M3 complete

* M1, M2 and M3 complete

* review changes

* docs

* docs
2026-04-16 23:11:26 +00:00

6.1 KiB
Raw Blame History

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 docs 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 documents 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 plans 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.