Make agent creation swarm-only and refuse a name placed on another hive
swarm-controller's POST /api/agents now refuses (409) a name the swarm
has already placed on a different hive: a non-Destroyed declaration in
that hive's wanted state, or a SetAgentWanted node still queued for it.
The same name on the same hive is that agent being re-created and goes
through. A wanted state that cannot be read refuses (503/500) instead of
reading as "placed nowhere". Creations are serialised from that read to
the graph insert so two concurrent creations of one name cannot both
pass.
Hive-level creation is removed: hivectl `agent create` / `request-create`,
HostRequest::Spawn / RequestSpawn, the dashboard POST /api/request-spawn
route, and ApprovalKind::Spawn with its approve/resolve arms and the
approval-carrying `templates::spawn`. The swarm path (deploy request or
wanted-state sweep -> queue_first_deploy -> templates::first_deploy) used
none of them. Old `spawn` approval rows are skipped by collect_lenient,
as `init_config` rows were in a3b672d1.
policy.rs's comment on agent_object_name stated swarm-wide name
uniqueness as a fact; it now says where it is enforced and what that
check cannot see.
Refs #4396
This commit is contained in:
parent
1d8ec00ddc
commit
5785c0024c
35 changed files with 376 additions and 434 deletions
|
|
@ -971,7 +971,6 @@ renderApprovals`) with three stacked sections:
|
|||
| `merge_config_pr` | `⇒` | `merge-pr` | PR-head sha (`sha_short`) |
|
||||
| `update_meta_inputs` | `↻` | `meta-update` | — |
|
||||
| `schedule_prompt` | `⏱` | `schedule` | — |
|
||||
| `spawn` | `⊕` | `spawn` | — |
|
||||
|
||||
<!-- vale write-good.Passive = NO -->
|
||||
The chip ticks live every second via a `data-requested-at`
|
||||
|
|
@ -985,7 +984,6 @@ renderApprovals`) with three stacked sections:
|
|||
config PR into `agent-configs/<agent>/pulls/<pr_number>` (shown
|
||||
only when `forge_present` is true and `pr_number` has a value). The config diff
|
||||
lives on the forge PR itself — no inline diff side-panel.
|
||||
- `spawn`: a one-line "container will be created" note instead.
|
||||
- **decision actions** — `◆ APPR0VE` and `DENY`. Deny pops a
|
||||
`prompt()` for an optional reason carried to the submitting agent as
|
||||
`HelperEvent::ApprovalResolved.note`.
|
||||
|
|
@ -1043,7 +1041,6 @@ below — some endpoints aren't in it yet.
|
|||
- `POST /api/{rebuild,kill,restart,start,destroy}/{name}` — lifecycle.
|
||||
`destroy` accepts `purge=on` to also wipe state dirs.
|
||||
- `POST /api/purge-tombstone/{name}` — wipe a tombstone's state dirs.
|
||||
- `POST /api/request-spawn` — queue a Spawn approval.
|
||||
- `POST /api/update-all` — rebuild every stale container.
|
||||
- `POST /api/rebuild-queue/{id}/cancel` — drop a `Queued` entry.
|
||||
Refuses `Running` / terminal-state entries (in-flight
|
||||
|
|
@ -1243,10 +1240,9 @@ payload):
|
|||
- `container_state_changed` (container: ContainerView) /
|
||||
`container_removed` (name) — per-row container mutations,
|
||||
emitted by `Coordinator::rescan_containers_and_emit` from
|
||||
many mutation sites — post-spawn approval bookkeeping
|
||||
(`actions::approve`), the job queue's own node execution
|
||||
(`job_queue::exec`, for example after a rebuild's stop/swap/start
|
||||
steps or a destroy's teardown step) — and from the 10s
|
||||
the job queue's own node execution (`job_queue::exec`, for example
|
||||
after a rebuild's stop/swap/start steps or a destroy's teardown
|
||||
step) — and from the 10s
|
||||
`crash_watch` poll. Client upserts/removes by name and
|
||||
reads the pending overlay from `transientsState` since the
|
||||
payload doesn't carry it.
|
||||
|
|
|
|||
Loading…
Reference in a new issue