Story: Investigate hand-added cross-service grants in generated iam_service_db_grants_create.sql

Table of Contents

This page documents a story in Sprint 25. It captures the goal, current status, acceptance criteria, and the tasks that compose it.

Goal

Understand why projects/ores.sql/create/iam/iam_service_db_grants_create.sql carries hand-added cross-service grants that the ores.codegen generator does not emit, and close the drift so that a regeneration from the service registry model is lossless — no load-bearing grant is ever silently dropped by a codegen run, and the committed file matches generator output exactly.

Status

Field Value
State DONE
Parent sprint Sprint 25
Now Nothing.
Waiting on Nothing.
Next Nothing.
Last touched 2026-08-05

Acceptance

  • Root cause documented: why the four hand-added grants exist (Acme provisioner logo access, party image soft-FK validation, cross-entity party membership), why the generator does not emit them, and whether they are correctly placed in the file.
  • A decision on the fix: extend the registry model/template with per-service cross-domain grant lists (generation becomes lossless), or an alternative that guarantees regeneration never silently drops grants (e.g. a generator guard that fails on unexpected manual content).
  • The committed file matches what the generator produces (regeneration is a no-op diff), or the drift is closed by an explicit mechanism with a test proving it.

Tasks

Task State Start End Description
Investigate and close the iam_service_db_grants_create.sql generator drift DONE 2026-08-05 2026-08-07 iam_service_db_grants_create.sql (generated via ores.codegen ores.sql.service address from the service registry model) carries four hand-added cross-service grants the generator does not emit: iam_service select on ores_assets_ + execute on ores_assets_get_template_image_fn (Acme provisioner logo copy) + select on ores_dq_ (cross-entity party membership); refdata_service select on ores_assets_ (party image soft-FK). A regeneration silently drops them. Investigate the root cause (model/template cannot express cross-domain grants), decide the fix (per-service cross-domain grant lists in the model, or a generator guard), implement it, and prove regeneration is now lossless (regenerate = no-op diff).

Decisions

  • Cross-service grant drift was a model gap, not a template gap: adding the missing prefixes to service_registry.org was sufficient — the template already has dml_prefixes, select_prefixes, and execute_prefixes sections that render to the right helper calls. No template change was needed.
  • Rationale comments for cross-service grants live in the model next to the prefix, not in the generated SQL — the generator cannot emit comments, and the model is the single source of truth.
  • The nats config path mismatch (nats-festive-dijkstra.conf vs. nats-festive_dijkstra.conf) was a convention drift between systemd_generate.py (using raw ORES_ENV_NAME with hyphens) and env_init.py (using label_lower with underscores, matching compass nats init's ORES_CHECKOUT_LABEL convention). Fixed in the systemd generator by mirroring env_init's label_lower conversion rather than changing the file-naming convention.
  • The OS sandbox was ruled out as a cause: after fixing the path mismatch, all 23 units started successfully with both global and project sandboxes active.

Out of scope

  • Removing or re-justifying the controller-era grants themselves — that is the decommission task's scope (26ABA6BB).
  • Any runtime grant changes beyond making generation lossless.

Emacs 29.3 (Org mode 9.6.15)