# Hub placement operations

Publishing an Environment makes it eligible for public discovery; it does not
place that Environment in Hub. Placement is a separate, manual curation action
performed by an Al-Amr Registry administrator after publication. No automatic
placement follows publication.

An external developer does not need access to the Al-Amr monorepo. They publish
the Environment through the normal workflow and give its stable `env_...`
identifier to an administrator. The administrator then uses Admin Panel or the
`alamr` CLI. Both surfaces call the same Registry management API.

## Authority boundary

| Owner                 | Responsibility                                                                                                                |
| --------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| Hub Environment       | Zone geometry, landmark meshes, labels, interaction, routing, and the finite logical slot inventory                           |
| Registry              | Current `slotId -> environmentId` assignment, catalog eligibility, uniqueness, administrator authorization, and audit history |
| Environment publisher | The independently authored Environment, immutable bundle revisions, optional owned backend, and public catalog presentation   |

Registry assignment never creates geometry or an arbitrary landmark. Admin
Panel and CLI can mutate only an existing `manual` slot. Creating, moving, or
removing a slot still requires an authored Hub change. A Zone remains local
Hub application state, not a Registry entity or independently authorized
Environment.

An assignment references the stable Environment ID rather than one revision.
Publishing a new active revision therefore does not require placement again,
provided the Environment remains public and catalog-eligible.

## Current inventory and states

The initial `env_hub` / `sunlit-way` inventory contains three first-party
`fixed` slots and the neutral `manual` slot `community-showcase-01`.

| Mode     | Meaning                                                         | Allowed administrator action                         |
| -------- | --------------------------------------------------------------- | ---------------------------------------------------- |
| `fixed`  | Authored first-party binding                                    | Read only; set, replace, and clear return a conflict |
| `manual` | Authored neutral landmark whose destination is Registry-managed | Set when empty; replace or clear when assigned       |

Every public slot has one derived state:

| State      | Meaning                                                                                                      | Public launch behavior                                                  |
| ---------- | ------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------- |
| `open`     | A `manual` slot has no assignment                                                                            | Show the authored open landmark; no launch action                       |
| `occupied` | Its assignment resolves to the exact active, published, public, catalog-eligible Environment                 | Expose the destination ID and use its Registry-owned launch payload     |
| `reserved` | A fixed slot is unassigned, an assigned destination is missing/ineligible, or placement truth is unavailable | Show the authored reserved landmark; no destination ID or launch action |

The administrator read model keeps `assignedEnvironmentId`, `updatedBy`, and
`updatedAt` so an operator can diagnose a reserved assignment. The public read
model exposes `destinationEnvironmentId` only for `occupied`; it never leaks a
stale target as enterable.

## Preconditions

1. The target Environment has an active revision whose publication submission
   is `published` with `public` visibility.
2. The target remains catalog-eligible: its active revision and installed
   Plugin releases are not blocked.
3. The target is not `env_hub` and is not already assigned to another slot in
   the same Hub.
4. The operator uses a real Registry administrator account. Project tokens and
   ordinary Project membership are insufficient.
5. Every set, replace, or clear operation includes a reason from 3 to 1000
   characters.

Registry rechecks these invariants during mutation. Hiding an option in Admin
Panel is usability, not authorization.

## Operator preflight

Before any set or replace, the operator verifies the full target state in one
pass:

1. The exact published active revision and its public catalog record resolve.
2. The Environment's Runtime and Presence are healthy, so the destination can
   actually be entered after placement.
3. The current slot state and any existing assignment are read from the
   administrator list, not assumed.
4. The reason for the mutation is decided before the write, because every
   mutation is audited with it.

## Admin Panel workflow

1. Sign in to the platform Admin Panel with a Registry administrator account.
2. Open `/placements` from **Hub placements**.
3. Confirm the page identifies `env_hub` and `sunlit-way` and inspect every
   slot's mode, state, current assignment, and last update.
4. For a `manual` slot, select an Environment from the public active inventory,
   enter the reason, and choose **Place in Hub** or **Replace destination**.
5. To remove an existing manual assignment, enter a separate reason and choose
   **Clear slot**.
6. Reload or list again and confirm the resulting `occupied`, `open`, or
   `reserved` state.

Fixed rows have no mutation controls. If the placement list cannot be verified,
Admin Panel disables every mutation. If only the eligible Environment inventory
is unavailable, assignment and replacement are disabled; a clear operation may
remain available when the authenticated placement record and CSRF session are
valid.

## CLI workflow

Authenticate with an administrator account. The public CLI defaults to the
production Registry; an explicit origin is useful when operating another
deployment:

```sh
alamr login --registry https://registry.al-amr.com
```

List the default Hub and Zone:

```sh
alamr admin hubs list --json
```

The explicit form is:

```sh
alamr admin hubs list env_hub sunlit-way --json
```

Assign an empty manual slot or replace its current destination:

```sh
alamr admin hubs set env_hub sunlit-way community-showcase-01 env_example \
  --reason "Approved community showcase" --json
```

Clear the assignment:

```sh
alamr admin hubs clear env_hub sunlit-way community-showcase-01 \
  --reason "Showcase period completed" --json
```

`list` defaults only its Hub and Zone operands. `set` and `clear` require every
identifier explicitly so an operator cannot mutate an inferred destination.
Structured output is contract-validated; an invalid Registry response fails
instead of being treated as success. Set, replace, and clear are independent
operations: each is evaluated against the current slot state at execution time,
and repeating the same clear leaves the slot `open` rather than producing a
second assignment change.

## Audit and failure behavior

Set/replace writes `hub.placement.set`; clear writes
`hub.placement.clear`. The audit record includes the administrator, Hub, Zone,
slot, destination, reason, and time. Assignment mutation and audit insertion
are one Registry transaction: if the audit write fails, the placement change
does not commit.

The current Hub page and `admin hubs` CLI commands do not render the audit
feed. An administrator verifies the stored event through the authenticated
`GET /v1/admin/audit-logs` management endpoint and correlates its
`resourceId` (`hubEnvironmentId:zoneId:slotId`) and metadata.

Expected conflicts include a fixed slot, Hub as its own destination, an
ineligible target, a missing target, and a target already assigned elsewhere.
Do not work around these errors by editing IDs or Hub source. Correct the
publication/catalog state or choose another eligible Environment, then repeat
the exact command.

Hub reads the public placement response and public Environment catalog on one
refresh boundary. If either source fails, it clears its resolved assignment
view and renders authored managed landmarks as reserved. It never falls back to
a hard-coded destination that could override an administrator's clear action.

## Operator verification

1. List the collection and confirm the intended slot is `manual`.
2. Set `community-showcase-01` to a public eligible Environment and confirm
   `occupied` plus the exact destination ID.
3. Open Hub and confirm the authored landmark uses the Registry launch payload;
   proximity alone must not navigate. Prove real entry into the placed
   Environment from Hub before considering the placement complete.
4. Clear the slot and confirm `open` in the next list/read refresh.
5. For negative evidence, make an assigned target ineligible and confirm the
   slot becomes `reserved` with no public destination or launch action.
6. Inspect the administrator audit feed for the matching set/clear reason.

See [Publication lifecycle](/docs/publish/publication-lifecycle) for the
distinct review and publication flow, and [CLI reference](/docs/reference/cli)
for the complete command surface.
