Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ A platform administrator works from a support or security request in a bright of

## Hierarchy

- Management-console logo, 256px tinted surface sidebar, and compact Lucide navigation.
- Management-console logo, 256px tinted surface sidebar, and compact Lucide navigation. Overview is the standalone first destination. `Admin Management` contains Workspaces, Users, and Platform Settings; `Governance` contains Admin Audit. Every established route remains unchanged.
- Workspaces use a distinct workspace-shell icon with a top bar and side panel; the Kubernetes Layers symbol remains reserved for cluster navigation. The Users workspace filter repeats the same workspace-shell icon.
- A persistent shield-labelled `Platform Admin` identity beneath the wordmark, reinforced by the favicon and browser title.
- The browser title stays concise as `Admin · AcornOps`; the fuller privileged context remains visible inside the interface.
Expand Down Expand Up @@ -40,7 +40,7 @@ A platform administrator works from a support or security request in a bright of
- Primary controls use the management console's dark neutral treatment and activation controls use Acorn orange.
- Directory toolbars follow the management console's inventory pattern: leading-icon search, high-value filters, a `Showing X of Y` loaded-result badge, and cursor-driven `Load more` pagination. Select controls use the management console's shared `Select` values directly: 44px default trigger, 16px horizontal padding, 14px medium UI type, orange interaction border/ring, fixed overlay layer 140, management menu shadow, compact-responsive option heights, and an orange-strong selected checkmark. Dropdown menus also use the management `custom-scrollbar` values: a 5px transparent track, orange 22% rounded thumb, and orange 40% hover thumb, with thin Firefox parity. By explicit platform-console refinement, chevrons remain muted grey when open and communicate state through rotation rather than color. The Users toolbar keeps its free-text workspace field, but workspace-name and ID suggestions use the same menu surface instead of a browser-native datalist. Its native browser clear glyph is replaced by a themed accessible clear control placed before the chevron. Platform clay remains wayfinding context and does not replace the shared orange control accent.
- The Workspaces toolbar uses the same inventory rhythm as Users with a leading-icon workspace-name search, a management-aligned All statuses/Active/Suspended dropdown, loaded-result badge, and cursor-driven pagination. A compact Active/Suspended column makes access posture scannable. Because the producer does not expose a lifecycle-status query, an active status filter exhausts the existing search cursor and filters the complete result set locally; the default unfiltered view remains paginated. Plan details remain in the panel. Search maps to the existing `q` producer query and does not claim ID or creator search that the producer does not provide.
- Selecting a workspace opens a deep-linkable right-side panel while retaining directory context. `Workspace Details` presents Kubernetes connections, virtual-machine connections, current plan, creator, and creation date in that order. Kubernetes and VM values use compact neutral connected/plan-limit counters derived from `/admin/v1/system/config`; red is reserved for over-limit exceptions because ordinary capacity is context, not a success state. `Change Plan` sits directly beside the current plan value so the action remains attached to the object it changes. The dialog contains only the plan selector and supplies an accurate system-generated reason without asking for a ticket or free-form reason. There is no quota-usage row, quota override action, or separate Manage Workspace section. The aggregate member count is attached to `Workspace Access`, directly above the read-only member-and-role table.
- Selecting a workspace opens a deep-linkable right-side panel while retaining directory context. The directory and `Workspace Details` render the creator using display name, email, and immutable user ID as fallbacks. `Workspace Details` presents Kubernetes connections, virtual-machine connections, current plan, creator, and creation date in that order. Kubernetes and VM values use compact neutral connected/plan-limit counters derived from `/admin/v1/system/config`; red is reserved for over-limit exceptions because ordinary capacity is context, not a success state. `Change Plan` sits directly beside the current plan value so the action remains attached to the object it changes. The dialog contains only the plan selector and supplies an accurate system-generated reason without asking for a ticket or free-form reason. There is no quota-usage row, quota override action, or separate Manage Workspace section. The aggregate member count is attached to `Workspace Access`, directly above the read-only member-and-role table.
- Workspace lifecycle is a distinct access-governance section with a more prominent Active or Suspended badge that matches the directory status vocabulary. Suspension and restoration both require typing the exact workspace name in the confirmation dialog; neither asks for a free-form reason or ticket reference, and each records an accurate system-generated reason with the administrator token. Cancel bypasses field validation and always closes the confirmation. Suspension blocks ordinary workspace-member authorization and discovery while retaining memberships, targets, workload state, references, and audit history. Restoration re-enables access through those retained memberships. Neither operation starts, stops, or modifies workloads.
- Workspace access rows are grouped by descending role privilege—Owner, Admin, Member, Auditor, Viewer, then unknown roles—and alphabetized by identity within a role tier. The default workspace view remains read-only. `Manage Access` switches the existing section into a deliberate workspace-scoped editor without navigating away. A compact person-plus action beside `Done` grants an existing user access and exposes its purpose through hover/focus text; rows update roles or revoke individual access. The complete authoritative page set disables the sole Owner while allowing co-owner changes, and the producer remains authoritative during races. Atomic ownership transfer remains contract-blocked. Bulk workspace revocation is intentionally absent from this surface. The Users panel remains the complementary user-scoped editor for managing one identity across workspaces; both entry points use the same fixed membership routes and role catalog.
- User filtering is limited to verification posture until the admin user contract exposes another actionable account state; disabled-user language must not be inferred from session or authentication data.
Expand All @@ -52,7 +52,7 @@ A platform administrator works from a support or security request in a bright of
- The select-then-update interaction is the explicit opt-in for a role mutation. It applies immediately without another dialog and sends an accurate system-generated reason required by the producer contract; optional `ticketRef` is omitted.
- `Workspace Access` lists workspaces alphabetically, shows the workspace count and a compact `Grant Access` action in its section header, and avoids a duplicate role badge. Membership lifecycle metadata sits in a quiet inline footer beneath the role controls so it remains visibly attached to the access record without competing with the workspace identity.
- Membership rows omit the raw `source` value because it has no authorization effect and can be mistaken for the user's authentication method. They show `Added` and, only when the displayed date differs, `Updated`; the footer wraps naturally on compact layouts.
- Admin Audit presents the authenticated human from the immutable OIDC issuer and subject. The ledger Actor column shows one readable administrator value only—recorded display name, then email, then immutable subject—without a role subtitle; the protected details retain the full governance-safe actor and credential evidence. The BFF workload token remains separate audit evidence and never substitutes for the human actor. The ledger translates known allowlisted action codes into concise Event labels and keeps the recorded reason directly beneath. Access grants and revocations display `Modified workspace access`, while role changes retain `Updated member role`; one `Modified workspace access` filter returns all three operations through a fixed producer `actionGroup`. Workspace suspension and restoration share `Modified workspace status`. Exact action codes remain visible as secondary context. Affected identifies `workspaceId` first, followed by `subjectType` and `subjectId` when both exist; workspace-only and subject-only events remain legible without inventing missing context. Pagination mirrors the management console audit log: 50-event cursor pages append in place, an intersection sentinel preloads the next page near the scroll boundary, and a visible secondary `Load more` button remains as the accessible fallback with loading and retry feedback.
- Admin Audit presents the authenticated human from the immutable OIDC issuer and subject. The ledger Actor column shows one readable administrator value only—recorded display name, then email, then immutable subject—without a role subtitle; the protected details retain the full governance-safe actor and credential evidence. The BFF workload token remains separate audit evidence and never substitutes for the human actor. The ledger translates known allowlisted action codes into concise Event labels and keeps the recorded reason directly beneath. Access grants and revocations display `Modified workspace access`, while role changes retain `Updated member role`; one `Modified workspace access` filter returns all three operations through a fixed producer `actionGroup`. Workspace suspension and restoration share `Modified workspace status`. Exact action codes remain visible as secondary context. Affected identifies the recorded workspace name first and falls back to `workspaceId`, followed by `subjectType` and `subjectId` when both exist; the immutable ID remains in projected event details and workspace filtering. Workspace-only and subject-only events remain legible without inventing missing context. Pagination mirrors the management console audit log: 50-event cursor pages append in place, an intersection sentinel preloads the next page near the scroll boundary, and a visible secondary `Load more` button remains as the accessible fallback with loading and retry feedback.
- Success toasts follow the management console pattern: centered bottom surface, success icon, dismiss action, brief entrance motion, and an Acorn orange expiry indicator. Messages state the completed outcome without duplicating audit implementation details.
- Membership suspension is an access state, not a role. The UI must not add `suspend` to the role catalog or label the existing membership `DELETE` operation as suspension. A future reversible action requires a dedicated `/admin/v1` suspend/restore contract; the current permanent removal is labelled `Revoke workspace access` and retains last-owner protection.
- Each access record exposes a compact revoke icon beside `Update Role`, never as a role option. Its hover tooltip and accessible name say `Revoke workspace access`. The individual control uses a persistent light-danger treatment and becomes solid danger on hover. Confirmation names the user and affected workspace scope without mentioning account lifecycle, sends a deterministic contract-required reason, and retains the producer's last-owner safeguard.
Expand Down
1 change: 1 addition & 0 deletions docs/contracts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ The console has one runtime service dependency: `control-plane`. It does not cal
- `lib/admin-contract.mjs` projects successful responses before browser delivery.
- Workspace operational summaries and operational admin-audit actions are removed even if the producer returns them.
- Admin audit attribution identifies the authenticated human from immutable OIDC issuer and subject fields, with display name and email snapshots for readability. The BFF workload token remains separate credential evidence.
- Workspace creator and admin-audit object labels are optional producer fields. The BFF projects them explicitly; the browser prefers the readable label and falls back to the immutable creator or workspace ID.
- The mock store emits producer-shaped DTOs before the same projection is applied.
- All accepted deviations are tracked in `DESIGN.md`.

Expand Down
3 changes: 2 additions & 1 deletion docs/contracts/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,13 @@
"workspacePlanPatchFields": ["planKey", "reason", "ticketRef?"],
"workspaceSuspendFields": ["workspaceName", "reason", "ticketRef?"],
"workspaceRestoreFields": ["workspaceName?", "reason", "ticketRef?"],
"adminWorkspaceResponseFields": ["clusterCount", "virtualMachineCount", "memberCount", "lifecycleStatus=active|suspended", "suspendedAt?"],
"adminWorkspaceResponseFields": ["createdByDisplayName?", "createdByEmail?", "clusterCount", "virtualMachineCount", "memberCount", "lifecycleStatus=active|suspended", "suspendedAt?"],
"memberCreateFields": ["userId", "role", "createUserIfMissing=false", "reason", "ticketRef?"],
"memberRolePatchFields": ["role", "reason", "ticketRef?"],
"memberDeleteFields": ["reason", "replacementOwnerUserId?", "ticketRef?"],
"responseCachePolicy": "All /admin/v1 responses set Cache-Control: no-store",
"adminAuditActorFields": ["adminActorIssuer", "adminActorSubject", "adminActorEmail?", "adminActorDisplayName?", "adminActorRole", "authenticationTime"],
"adminAuditObjectFields": ["workspaceId?", "workspaceName?", "subjectType?", "subjectId?"],
"privacyProjection": "BFF removes operational workspace fields, filters admin audit to governance action families, and removes target/run identifiers before browser delivery"
}
}
Expand Down
50 changes: 50 additions & 0 deletions docs/exec-plans/completed/admin-readable-identities.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Admin Readable Identities

Status: completed
Branch: `fix/admin-readable-identities`
Producer: `control-plane`

## Goal

Replace raw creator and workspace IDs in routine platform-admin displays with
readable labels while retaining immutable IDs for filtering, details, and
fallback.

## Constraints

- Browser traffic remains on same-origin `/admin-console-api/*`.
- The BFF explicitly projects every new field.
- Creator display order is display name, email, then immutable user ID.
- Audit object display order is workspace name, then immutable workspace ID.
- Operational fields, workspace audit events, and unrestricted metadata remain
unavailable.

## Requirement Classification

- `REQ-WSP-002`: add a readable creator-display rule.
- `REQ-AUD-001`: replace workspace-ID-first object display with
workspace-name-first display and immutable-ID fallback.
- `REQ-BND-002` and `REQ-BND-003`: preserved.

## Validation Log

- `npm run validate`: passed.
- All 95 tests passed, including creator-label precedence, immutable-ID
fallbacks, workspace-name audit objects, and BFF confidentiality projection.
- Lint, contract checks, requirement checks, harness checks, the production
build, and static/API/denial smoke routes passed.
- The rebuilt `platform-admin-console` container is healthy and connected to the
rebuilt control plane.
- Live control-plane data resolves `Development Workspace` to creator
`Dev User`, and all 10 current workspace audit events include
`workspaceName`.
- Browser rendering reached the healthy platform-admin sign-in flow; final
authenticated visual inspection requires the user to sign in because no
reusable authenticated browser session was available.

## Completion Criteria

- Workspace directory and details use readable creator labels.
- Admin Audit uses workspace names in the Object column and details.
- Focused projection and rendering regressions pass.
- Requirements, contract, repository, and live browser checks pass.
Loading
Loading