Skip to content

fix(workforce-validation): detach UUID storage behind immutable registry value objects #243

Description

@seonghobae

Finding

Draft #235 made ValidationPrincipal, ValidityStudyRecord, and ValidityStudyView tuple-backed, but exact uuid.UUID members were still retained as caller/repository object aliases. Python permits object.__setattr__(uuid, "int", ...), so a retained exact UUID reference could mutate identity evidence inside an otherwise immutable outer tuple after constructor validation. The same aliasing allowed an executable repository callback to mutate the tenant/study UUID objects passed to it and return a record matching the rewritten target, making a post-port comparison self-consistently accept an identity different from the one originally authorized.

This is distinct from #236/#237/#241, which protect outer value-object fields. #243 covers nested UUID aliases in principal, persisted record, authorized view, UUID-valued criterion_blueprint_id, and the read-port target boundary.

Test-first ordinary repair

Canonical #235 advanced from #242 head 412c62b279a4d3b5448dd2817c835e0aa85b412d through:

  • dfd8038e83270c8530c5a5ef7d2bfb1af409490b: retained constructor UUID aliases must not rewrite principal/record evidence; a UUID read from ValidityStudyView.fields must not mutate a subsequent projection read.
  • a78104c71e340039ca7f0c36aa2d4f7d22dff999: _TargetSwitchingReadPort mutates received tenant/study UUIDs and returns a record matching the switched target; the application must reject it as another target.
  • b1c70855e6655817a4f40cc9dfb4787770f40c5d: production stores validated UUID authority as immutable integer payloads, reconstructs fresh exact UUIDs at public/callback boundaries, snapshots tenant/study authority before authorization, and binds post-port verification to those immutable snapshots. Policy tenant detachment receives the same treatment.
  • 65052598187e8b7b177f58e65f83d004dbfa8f83: README makes the UUID alias/storage and target-snapshot semantics code-current.

The test-only heads were superseded before hosted execution, so no hosted RED is claimed. CodeRabbit independently reviewed exact 65052598187e8b7b177f58e65f83d004dbfa8f83 against protected develop@eb9757f8649aaad026a9865508d9aad50c1a7a4f and reported no blocking defect in the requested #243 scope. That evidence remains valid for the #243 repair commit but is not transferred as current merge evidence after later successors.

Successor preservation and current acceptance

#235 has since advanced through #244 to exact 7c71f81c63ff87d6524fd565b3b5ce444905ca2e, still open · Draft · mechanically mergeable over protected develop@eb9757f8649aaad026a9865508d9aad50c1a7a4f. #244 further hardens _require_operational_uuid(...) so a forged exact UUID with an executable/non-integer internal int payload is rejected before equality/range behavior; it does not reopen #243. Integer UUID storage, fresh public/projected UUID reconstruction, and immutable pre-port target binding remain intact.

CodeRabbit independently reviewed current exact 7c71f81c63ff87d6524fd565b3b5ce444905ca2e for #244 and explicitly confirmed preservation of #243 plus #239#242 ordering. This is current-head static evidence only, not a ruleset-qualifying APPROVED review.

Exact current-head Foundation 33962944744 / Repository quality 101297910519 remains queued before checkout with steps=[], ubuntu-24.04, and runner_id=0. CodeQL PR 33962944749, SAST Semgrep 33962944737, Security Scan 33962944753, Noema 33962943840, OpenCode 33962943857, Strix 33962943816, and required PR scheduler 33962943848 are also non-terminal. No hosted GREEN, 100% owned statement/branch coverage, executed PostgreSQL GREEN, terminal security completion, or qualifying approval is claimed.

Keep this issue open through exact-head hosted/security acceptance, qualifying ordinary review, and normal protected integration. Do not weaken exact UUID/sentinel validation, Keyverse authorization ordering, owner-schema bootstrap, Foundation coverage gates, or cross-context SQL boundaries.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions