Give 2-BM two human principals, with their names never in the repo - #746
Merged
Merged
Conversation
Every run at 2-BM is recorded against the seeded RunWitness agent, because CORA observes the EPICS capture rather than issuing it. No human principal exists at the beamline at all, so there is nothing to act as while testing and nothing but an agent in proj_run_actor_involvement. Seed the two staff as human Actors under pinned, deployment-stable ids so they become usable principals now, and leave the shape of what they may do for later. The display names are personal data and this repository is public, so the repo carries only opaque seat ids and kind=human. Each name is supplied at deploy time from the host environment and lands solely in the actor_profile PII vault, matching the pattern register_actor already follows: the ActorRegisteredV2 payload has no name in it. A slot with no configured name fails before any database connection rather than seeding a blank, and the error names the slot and its environment variable, never a value, so it is safe to print or paste. This is a CLI ceremony in pilot_seed.py's shape, not a boot-lifespan hook like the agent and enclosure seeds. Those can run on every boot because an absent config value makes them a safe no-op; a fail-loud name requirement cannot, since it would stop every other deployment from booting unless it also configured two 2-BM names it has no reason to know. No Trust Policy is seeded and trust_policy_id stays unset, so AllowAllAuthorize remains in force. A permissive policy looked attractive as a way to exercise the authorize path early, but there is no canonical command registry to enumerate from, so its permitted_commands would be a hand-copied list that fails closed the first time a new slice ships. That needs an architecture fitness test tying the seeded set to the discovered wire commands, and belongs in its own change. governance.md now records what is actually true, including that TrustAuthorize loads exactly one Policy per deployment, so the two-Policy split it used to describe is not a shape Settings can express. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Coverage reportClick to see where and how coverage changed
This report was generated by python-coverage-comment-action |
||||||||||||||||||||||||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Every run at 2-BM is recorded against the seeded
RunWitnessagent, because CORA observes the EPICS capture rather than issuing it. No human principal exists at the beamline at all, so there is nothing to act as while testing and nothing but an agent inproj_run_actor_involvement.This seeds the two beamline staff as
humanActors under pinned, deployment-stable ids, so they become usable principals now. What they may do is deliberately left for later.Names never enter the repository
The display names are personal data and this repository is public. The repo carries only opaque seat ids and
kind=human. Each name is supplied at deploy time from the host environment and lands solely in theactor_profilePII vault, matching the patternregister_actoralready follows: theActorRegisteredV2payload has no name in it.A slot with no configured name fails before any database connection is opened rather than seeding a blank, and the error names the slot and its environment variable, never a value, so it is safe to print, log, or paste.
Two integration tests pin this directly against Postgres rows:
test_seeded_event_payload_carries_no_nameandtest_seeded_name_lands_only_in_the_profile_vault.A CLI ceremony, not a boot hook
pilot_seed.py's shape, not_agent_seed.py's. The automatic seeds can run on every boot because an absent config value makes them a safe no-op. A fail-loud name requirement cannot: wiring it into the boot path would stop every other deployment (dev, CI, test, any other facility) from booting unless it also configured two 2-BM names it has no reason to know.Run it with
python -m cora.api.beamline_staff_seed. Idempotent;--dry-runsupported.Identity range
02900000-0000-7000-9000-..., distinct from the seeded-agent range01900000-0000-7000-8000-...in both the top segment and the fourth-group nibble, so a UUID alone tells you whether a principal is a human seat or an agent. Verified collision-free against every literal UUID in the repo, and pinned by a unit test.No Policy, deliberately
trust_policy_idstays unset, soAllowAllAuthorizeremains in force and behavior is unchanged.A permissive real Policy looked attractive as a way to exercise the authorize path before it can deny anything. It does not survive contact: there is no canonical command registry in
srcto enumerate from, sopermitted_commandswould be a hand-copied list that fails closed the first time a new slice ships. That needs an architecture fitness test tying the seeded command set to the discovered wire commands, and belongs in its own change.docs/deployments/2-bm/governance.mdnow records what is actually true, replacing three placeholder operators that no code ever created. It also notes thatTrustAuthorizeloads exactly one Policy per deployment (Settings.trust_policy_idis a single optional UUID), so the two-Policy split the page used to describe is not a shapeSettingscan express.Verification
One note on the architecture tier. It iterates
tracked_python_files(), so it silently skipped all three new files until they were staged. Staged first, it caught a real violation (a public*Errorclass outside the aggregate kernel), now fixed by making the class module-private per the test's documented exemption for tool-local validation helpers.Known behavior worth flagging
Re-running with a corrected name changes nothing: the ceremony returns early when the actor already exists, so fixing a typo in a display name currently needs a manual vault edit. Consistent with "idempotent, re-runs change nothing", but not obvious.
🤖 Generated with Claude Code