Task: Give installation-scoped data its policy shape

Table of Contents

This page documents a task in the Story: Name the installation's own data story. It captures the goal, current status, acceptance, and any notes or results.

1. Goal

Add a row-level-security feature to the entity meta-model that emits the installation's policy shape – own tenant or system-tenant rows – and declare it on the grid and node samples, so a model states its owner instead of a hand-written policy doing it.

2. Status

Field Value
State DONE
Parent story Story: Name the installation's own data
Now Nothing.
Waiting on Nothing.
Next Nothing.
Last touched 2026-10-07

3. Acceptance

  • The entity meta-model has a row-level-security feature that emits the installation's policy shape – for all using (tenant_id = ores_iam_current_tenant_id_fn() or tenant_id = ores_utility_system_tenant_id_fn()) with check (tenant_id = ores_iam_current_tenant_id_fn()) – so a model states its owner instead of hand-writing the policy.
  • The feature's name and doc comment cannot be confused with :rls_system_tenant_visible:, which emits the guarded current = system widening. A codegen test proves the emitted shape and that it carries no widening.
  • The ores.compute.grid_sample and ores.compute.node_sample models declare the feature and :tenant_read_scope: shared, so their generated reads carry no tenant predicate and the policy decides.
  • The guard reports the same 10 listed widenings and no new one, and the codegen suite passes.
  • The regenerated compute SQL carries the shape, and the component drift gate reports no drift.

4. Plan

(Implementation strategy. Written when work starts; key decisions are distilled into the parent story's * Decisions at close, but the plan itself stays — it is the historical record of what we did.)

5. Measurements

Every number this task claims about a tree, with the command that produced it and the commit it was measured at. A number without both is not a measurement, because a clean-up record describes a tree and trunk moves under a branch: a consumer count, a gate's component count and a suite's size all change with no code changing, and the reader of a bare number cannot tell which tree it came from. Where the raw output matters, put it in an evidence/ file beside the task and name that file in the Command column.

What Value Command Commit
Codegen suite 1281 passed projects/ores.codegen/venv/bin/python -m pytest projects/ores.codegen/tests -q 67854ba50e
Widening guard 10 widenings, 0 new projects/ores.codegen/scripts/check_rls_system_tenant_widenings.py 67854ba50e
Full build exit 0 ./compass.sh build 77ad089668
Full suite 94/94 targets pass ./compass.sh test run 77ad089668
Doc validation 42 components pass projects/ores.codegen/validate_docs.sh 77ad089668

6. Notes

7. Test Scenarios

Manual QA scenarios (scaffolded via compass add test_scenario) 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
     

8. PRs

PR Title
#2761 [compute,codegen] Name the installation's own data

9. Review

# Comment summary File Decision Notes
1 Junctions parse the same * SQL / ** Flags drawer and were wired to the new flag, but no validator ran for them: own-or-system without tenant isolation emitted no policy, and both flags together emitted the widening core.py, junction template Accepted Ran validate_rls_isolation on junctions; kept the flag wired because a real system-tenant-readable junction needs the shape; added three junction tests
2 The story Status still said BACKLOG and its Next still said "Break the story into tasks" while both tasks were DONE, and its acceptance named work the tasks do not do story.org Accepted Story re-scoped, marked DONE once the trimmed acceptance was met, and the remaining migration carried into a successor story

10. Result

ores.sql.schema gained :rls_own_or_system_tenant_rows:. It emits the installation's policy shape – own tenant or system-tenant rows for reads, the current tenant for writes – in the tangled domain-entity and junction create templates. It refuses to appear without :rls_tenant_isolation: and refuses to sit beside :rls_system_tenant_visible:, so a model cannot ask for both shapes at once. The name states the rows the policy admits on the tenant_id side, not the session, so it cannot be confused with the guarded current = system widening; the justification is a comment in the entity meta-model.

ores.compute.grid_sample and ores.compute.node_sample declare it with :tenant_read_scope: shared, so their generated reads state no tenant predicate and the policy decides. The regenerated SQL emits the shape for both samples, and the ER .puml is refreshed.

Gates: check_rls_system_tenant_widenings.py reports 10 widenings, all listed, and no new one; the codegen suite passes 1281 tests; check_component_drift.py --all reports no drift; validate_docs.sh passes all 42 components; the full build and the 94-target suite are clean.

Emacs 29.3 (Org mode 9.6.15)