Task: Bind ores.iam entities to profiles; verify zero-diff regen

Table of Contents

This page documents a task in the Entity classification and drift baseline: ores.iam story. It captures the goal, current status, acceptance, and any notes or results.

1. Goal

Survey every ores.iam entity (projects/ores.iam/modeling) against the profile catalogue, rebind matches, regenerate, and require zero additional diff against the pre-rebind checked-in output.

2. Status

Field Value
State DONE
Parent story Entity classification and drift baseline: ores.iam
Now Nothing.
Waiting on Nothing.
Next Nothing.
Last touched 2026-09-05

3. Acceptance

  • Every entity discovered under projects/ores.iam/modeling is surveyed against all Variability Profiles.
  • Every matching entity is rebound and regenerated with zero additional diff versus its pre-rebind checked-in output.
  • No-match entities are recorded with their actual feature values, not silently dropped.
  • The tenant_type has_tenant_id model/table drift is resolved as part of this survey, not carried forward as a separate open item.
  • The known service_find_prefix gap on tenant_type and tenant_status is resolved as part of reaching zero drift.

4. Plan

4.1. Survey (2026-09-05)

All six codegen-eligible orgs under projects/ores.iam/modeling were surveyed against the profile catalogue; there is no genuine no-match. The iam and iam-cpp catalogue entries share this modeling_dir, so this is one survey.

Org Kind Profile Change in this unit
ores.iam.tenant entity uuid-identified-lookup SQL rules and :unique: declared (below)
ores.iam.account_party_junction junction tenant-scoped-junction soft-FK declarations (below)
ores.iam.account_contact_information entity self-referencing-hierarchy profile declared
ores.iam.account_type entity simple-lookup (+ service_find_prefix) none; pre-bound, byte-stable
ores.iam.tenant_status entity simple-lookup (+ service_find_prefix) none; pre-bound, byte-stable
ores.iam.tenant_type entity simple-lookup (+ service_find_prefix) none; pre-bound, byte-stable

Known starting-point items from the story acceptance:

  • service_find_prefix on tenant_type and tenant_status was already declared at the branch point; both orgs regenerated byte-identically through this unit.
  • The tenant_type has_tenant_id model/table drift was investigated and closed before this unit branched (see Notes: capture 2F793500…). This unit's zero-diff regeneration independently confirms the model set and the committed schema agree.

4.2. SQL rule restorations

Every committed SQL rule for the regenerated tables was restored through codegen, per the standing directive to extend codegen rather than drop SQL (see Notes, #1961 audit):

Committed rule (pre-rebind SQL) Org declaration this unit Template feature
four table checks (system-tenant id/code guard, system tenant_id, code <> '', hostname <> '') tenant.org * SQL ** Checks Checks section (pre-existing)
delete rule sets status = 'terminated' tenant.org ** Delete sets Delete sets section (new, 29438cdb8e)
unique index on hostname (active records) hostname column :unique: true unique-non-key column feature (new, 29438cdb8e)
type/status FK validation on insert (23503) tenant.org * Insert trigger ** Validations Validations table wiring generated validate fns (pre-existing)
account_party soft-FK validation blocks account_party_junction.org * Foreign keys junction soft-FK section (pre-existing)

The checks and the junction FK blocks regenerate byte-identically to the committed rule text (verified hunk-for-hunk, zero diff). The hostname index differs only by the idiom comment the template adds. The validate-fn wiring keeps the 23503 rejection rule; message text and bootstrap behaviour differ from the committed inline blocks and are accepted as an idiom improvement (Notes).

The remaining SQL delta is template-era modernization, the sign-off class that refdata anchors already carry: clock_timestamp in place of current_timestamp, security definer as a function attribute on entity insert fns, the junction insert fn dropping its legacy security-definer attribute to the plain idiom all nine committed refdata junction outputs ship, and delete-rule parens. Regeneration also surfaced a latent generator bug the old template never rendered: the tenant name snippet called the nonexistent faker::company::name(), fixed to faker::company::companyName() to match every sibling org (05c1a89a2d).

4.3. Commit sequence

  1. 29438cdb8e [ores.codegen] template features + parser coverage.
  2. 8e077020be [iam] modeling org declarations.
  3. 5395fe890e [iam] regenerated outputs (63 files; SQL rule restorations, era modernization, bound-profile C++/Qt growth).
  4. 90fc228c60 [agile] task start flips.
  5. b85c6ac327 [ci] drift gate extended to iam,iam-cpp.
  6. 05c1a89a2d [iam] tenant generator faker fix.
  7. bec4d7d61d [ores.iam] restore the tenant provisioning protocol and handler lost in the C3 regen (custom flow, no template output path).
  8. ffc22e94f6 [agile] record the iam survey and SQL rule restorations.
  9. ef7a2a8ee2 [iam] restore the cross-tenant tenant_lookups lost in regeneration (hand-authored; RLS-subject plain reads).
  10. e8094a710d [shell, qt] adapt the tenant history command to the regenerated response member.
  11. d61e26fd61 [ores.qt] adapt IamPlugin to the regenerated TenantController API.
  12. 4e3fc08cd6 [ores.codegen] seed transitive FK ancestors in generated eventing tests.
  13. 4bad7fffe7 [iam] fix the tenant type generator; declare the account seeding snippet in the org.
  14. 53363539e8 [iam, compute, refdata] regenerate outputs after seed closure and generator fix.
  15. 5ea58e41b2 [ores.codegen] split ancestor seeding into declare and write phases.
  16. 94ade14712 [compute, refdata] regenerate eventing tests after the two-phase seeding split.
  17. 5433e022c5 [ores.codegen] let the parent_seed org block name its own includes.
  18. 7de2f9b47e [iam] declare the account seeding includes in the contact-information org.
  19. 6ada58025f [ores.codegen] emit the parent_seed snippet's named includes in the test head.
  20. a9ecc71021 [ores.codegen] suffix synthetic :unique: plain-string columns with the process counter.
  21. aaab07e8c1 [ores.codegen] emit the system-scoped write context in generated eventing tests.
  22. 72687b2bb2 [ores.iam] regenerate the tenant generator and eventing test; sweep tenants.
  23. 15e4abbc25 [ores.iam] align the tenant lookup test with the tenants_read_policy design.

5. Notes

  • #1961 audit: the PR that first regenerated the iam lookup SQL under the then-new lookup templates was audited for dropped rules. The audit found adds-only: the committed tree gained the generated validate fns and their wiring; no committed rule was dropped and no rule text was weakened. #1961 does not set a drop-SQL precedent, so this unit followed its lead: every rule the pre-rebind iam SQL carried has a codegen home in the committed tree today.
  • The tenant type/status validation idiom changes shape: committed inline blocks raised 23503 with bespoke messages; the regenerated tables call the generated ores_iam_validate_tenant_type_fn and ores_iam_validate_tenant_status_fn (lookup SQL), which raise 23503 with an allowed-values listing and pass through bootstrap inserts while the lookup has no active system rows. Rule semantics (reject unknown type/status at insert) are unchanged.
  • tenant_type has_tenant_id drift (capture 2F793500-FBD1-4E4F-8B6E-15D03337FBD2): closed pre-branch by the ir-curve-followups task (task_tenant_type_has_tenant_id_drift.org, DONE), which deleted the three _lookup_entity.org duplicates; the simple-lookup entity orgs are the sole authority and regenerate byte-identically.
  • The superseded ad hoc task 'Apply safe drift to iam-cpp' (task_apply_safe_drift_iam.org) is ABANDONED and already points to this story.

6. Test Scenarios

Manual QA scenarios (scaffolded via compass add test_scenario, run through the QA Validation Runner panel) that verify this task. Link new ones here as they're created; the scenario doc itself links back via its "Verifies task" field.

Scenario State Notes
     

7. PRs

PR Title
#2014 [iam,codegen] Bind iam entities to profiles, zero-diff regen

8. Review

# Comment summary File Decision Notes
1 Regenerated tenant.hpp documents the system tenant UUID as all zeros; the system tenant id is the max UUID (ffffffff-ffff-ffff-ffff-ffffffffffff), per tenant_id::system(), ores_utility_system_tenant_id_fn() and the tenant table's own check ores.iam.tenant.org Accept Org prose (overview, id column description) corrected at source and regenerated; tenant.hpp and iam_tenants_create.sql doc comments now state the max UUID (15bd8482d0)

9. Result

Closed 2026-09-05. Bound the six ores.iam codegen-eligible orgs per the Plan survey: ores.iam.tenant to uuid-identified-lookup, ores.iam.account_party_junction to tenant-scoped-junction, ores.iam.account_contact_information to self-referencing-hierarchy; account_type, tenant_status and tenant_type were pre-bound simple-lookup entities and regenerated byte-identically through the unit. Every committed SQL rule the pre-rebind iam tables carried has a codegen home: the four tenant table checks via the Checks section, the status = 'terminated' delete rule via the new ** Delete sets section, the hostname active-record unique index via the new column :unique: flag, the type/status insert validations via the generated lookup validate fns, and the account_party soft-FK blocks via the junction foreign-keys section. Template-era modernization on the regenerated tables (clock_timestamp, the security-definer function-attribute form, the junction insert fn losing its legacy attribute) is the sign-off class the refdata anchors already carry; regeneration also surfaced a latent generator bug the old template never rendered, the tenant name snippet calling the nonexistent faker::company::name(), fixed to companyName() to match every sibling org (05c1a89a2d).

Regeneration surfaced two further losses from the earlier C3-era regeneration, both restored at source: the tenant provisioning protocol and handler (a custom flow with no template output path, restored by hand, bec4d7d61d) and the cross-tenant tenant_lookups (the hand-authored counterpart of tenant_repository; no template emits the file, and it keeps the pre-rebind unfiltered reads, ef7a2a8ee2). The shell tenant-history command and the qt IamPlugin were adapted to the regenerated APIs (e8094a710d, d61e26fd61). The drift gate now covers iam and iam-cpp (b85c6ac327, per the compute unit's extension of the compass-pr-raise check list); a full retangle leaves the tracked tree byte-identical to the committed output.

Moving the acceptance runs onto a recreated test DB (compass db recreate) surfaced three defects the previous DB had masked, each fixed at source rather than worked around. Generated eventing tests now seed transitive FK ancestors in a two-phase declare/write split and write under the system-scoped context (4e3fc08cd6, 5ea58e41b2, aaab07e8c1); synthetic :unique: plain-string columns take the process-counter suffix, ending the tenant-hostname collisions on unique indexes (a9ecc71021); and the tenant lookup test now asserts what the committed tenants_read_policy admits – the row's own tenant context and the system context resolve the system-owned tenant rows, a peer tenant's context stays isolated – with the constraint documented in the tenant_lookups header (15e4abbc25).

Acceptance: every entity surveyed and every match rebound (survey table above); regenerated output byte-identical to the committed tree for refdata, reporting, marketdata, compute-cpp, iam and iam-cpp (check_component_drift.py, 2026-09-05); no genuine no-match; the tenant_type has_tenant_id drift closed pre-branch and independently confirmed by the zero-diff regen; the service_find_prefix gap on tenant_type and tenant_status was already declared at the branch point and stayed byte-stable; full build clean at 100% with ores.qt.exe linked (linux-clang-debug-make); ctest 71/71 green on the recreated DB; iam and iam-cpp covered by the drift gate.

Emacs 29.3 (Org mode 9.6.15)