portal-mojo 0.2.18 → 0.2.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -0
- package/docs/README.md +1 -1
- package/docs/admin-assistant.md +152 -1
- package/docs/admin-credentials.md +38 -0
- package/docs/admin-dns-certificates.md +160 -0
- package/docs/admin-dns.md +16 -0
- package/docs/admin-fleet-configuration.md +98 -2
- package/docs/admin-identity-directories.md +12 -0
- package/docs/admin-identity-users.md +10 -0
- package/docs/admin-modals.md +28 -0
- package/docs/auth-pages.md +18 -6
- package/docs/auth.md +16 -2
- package/docs/collection-select.md +14 -0
- package/docs/grouping-and-fmt.md +1 -1
- package/package.json +1 -1
- package/src/account/PasskeyList.tsx +1 -1
- package/src/account/credential-models.ts +2 -1
- package/src/admin/assistant/AssistantSetupPage.tsx +196 -0
- package/src/admin/assistant/index.ts +2 -0
- package/src/admin/assistant/setup.ts +174 -0
- package/src/admin/core/index.ts +14 -4
- package/src/admin/credentials/AcmeConsumerKeyDialog.tsx +88 -0
- package/src/admin/credentials/acme-consumer-key.ts +34 -0
- package/src/admin/credentials/group-api-keys.tsx +5 -3
- package/src/admin/dns/CertificateDetail.tsx +8 -3
- package/src/admin/dns/CertificateRequestDialog.tsx +45 -7
- package/src/admin/dns/DomainDetail.tsx +7 -1
- package/src/admin/dns/DomainsPage.tsx +6 -2
- package/src/admin/dns/SharedValidationDialog.tsx +298 -0
- package/src/admin/dns/SharedValidationPanel.tsx +76 -0
- package/src/admin/dns/shared-validation-api.ts +90 -0
- package/src/admin/dns/shared-validation-data.ts +106 -0
- package/src/admin/domains/assistant.ts +1 -0
- package/src/admin/domains/operations.ts +6 -4
- package/src/admin/fleet-configuration/FleetConfigurationPage.tsx +14 -8
- package/src/admin/fleet-configuration/SharedValidationConnectionPanel.tsx +166 -0
- package/src/admin/fleet-configuration/data.ts +4 -0
- package/src/admin/fleet-configuration/operator-destinations.ts +20 -0
- package/src/admin/fleet-configuration/shared-validation-data.ts +143 -0
- package/src/admin/identity/groups/group-sections/SubGroupsSection.tsx +73 -2
- package/src/admin/identity/groups/models.ts +2 -0
- package/src/admin/identity/users/UserDetail.tsx +1 -0
- package/src/admin/identity/users/sections/SecuritySection.tsx +4 -0
- package/src/admin/identity/users/sections/actions.tsx +75 -2
- package/src/admin/identity/users/sections/shared.tsx +18 -7
- package/src/client/auth.ts +77 -25
- package/src/client/fleet-mock.ts +73 -1
- package/src/client/index.ts +4 -2
- package/src/client/mock.ts +427 -14
- package/src/styles/components/admin-assistant.css +22 -0
- package/src/styles/components/admin-dns-certificates.css +33 -0
- package/src/ui/CollectionSelect.tsx +30 -8
- package/src/ui/date/fns.ts +32 -0
- package/src/ui/format.ts +26 -1
- package/src/ui/grouping.ts +31 -16
- package/src/ui/menu-registry.ts +3 -0
package/README.md
CHANGED
|
@@ -145,3 +145,15 @@ The non-negotiables live in the repo root `PLAN.md` ("Architecture rules") and
|
|
|
145
145
|
boundary; failure is unmissable; controlled inputs only; models are
|
|
146
146
|
definitions + hooks (TanStack Query owns cache); `ReactNode` slots, never
|
|
147
147
|
trusted-HTML strings; both themes from day one.
|
|
148
|
+
|
|
149
|
+
### Owner-only AI Assistant setup
|
|
150
|
+
|
|
151
|
+
The Assistant domain includes a dedicated `/assistant/setup` page (also embedded
|
|
152
|
+
under the Admin mount prefix), protected by the additive literal-superuser
|
|
153
|
+
`AdminRoute.requireSuperuser` / `MenuItem.requireSuperuser` gate. It provides
|
|
154
|
+
explicit key check/save and enablement, with separate advanced Platform key,
|
|
155
|
+
deployed policy/safety, remote access and incident triage sections. Setup secrets
|
|
156
|
+
and actions stay page-local and cache-free. Fresh-auth requires key re-entry,
|
|
157
|
+
and deployment owns the runtime route. See [Admin Assistant](docs/admin-assistant.md)
|
|
158
|
+
for exact schema-2 actions, lifecycle guarantees, mock showcase and verification;
|
|
159
|
+
[Admin credentials](docs/admin-credentials.md) documents the shared core gate.
|
package/docs/README.md
CHANGED
|
@@ -41,7 +41,7 @@ everything: run the showcase (`npm run dev:showcase`) → **Develop → Componen
|
|
|
41
41
|
| [admin-messaging.md](admin-messaging.md) | SES domains/mailboxes/sent/templates plus public contact requests, with write-only credentials and offline HTML previews |
|
|
42
42
|
| [admin-phonehub.md](admin-phonehub.md) | Global Phone Hub: evidence-backed lookup, sanitized SMS audits, and write-only provider configuration |
|
|
43
43
|
| [admin-push.md](admin-push.md) | Global Push admin: caller stats, global metrics, strict audits, templates, and cache-free FCM configuration |
|
|
44
|
-
| [admin-assistant.md](admin-assistant.md) |
|
|
44
|
+
| [admin-assistant.md](admin-assistant.md) | Owner-only AI Assistant Setup, credential/safety/remote controls and global Assistant streaming selection/reconciliation, strict projectors/blocks, context reuse, skills, and explicit tiered memory |
|
|
45
45
|
| [ModelTable.md](ModelTable.md) | The server-driven table: columns, filters, selection/batch, chooser, persist, autoRefresh, expand, groupBy, export, skeleton |
|
|
46
46
|
| [forms.md](forms.md) | The `Field` language, `SchemaForm`, `formModal`, `FormView` inline autosave + showWhen + tabsets |
|
|
47
47
|
| [tabs-and-form-wizard.md](tabs-and-form-wizard.md) | Accessible Tabs variants and shared-state FormWizard, async finish, reset/roster semantics, modal helper |
|
package/docs/admin-assistant.md
CHANGED
|
@@ -2,7 +2,158 @@
|
|
|
2
2
|
|
|
3
3
|
Import from `portal-mojo/admin`.
|
|
4
4
|
|
|
5
|
-
`ASSISTANT_ADMIN_SECTION` registers Conversations, Skills, and Memory beneath the Assistant navigation group. Its section clause is global-only ANY-of `sys.view_admin` or `sys.assistant`; Memory narrows its route to `sys.assistant`, matching the backend. Active-group grants never reveal it. `AssistantLauncher` uses the section gate. `AssistantContextLauncher` additionally requires `sys.view_security` or `sys.security` and only accepts `incident.Incident` or `incident.Ticket`.
|
|
5
|
+
`ASSISTANT_ADMIN_SECTION` registers Setup, Conversations, Skills, and Memory beneath the Assistant navigation group. Its section clause is global-only ANY-of `sys.view_admin` or `sys.assistant`; Memory narrows its route to `sys.assistant`, matching the backend. Active-group grants never reveal it. `AssistantLauncher` uses the section gate. `AssistantContextLauncher` additionally requires `sys.view_security` or `sys.security` and only accepts `incident.Incident` or `incident.Ticket`.
|
|
6
|
+
|
|
7
|
+
## AI Assistant setup
|
|
8
|
+
|
|
9
|
+
`AssistantSetupPage` is a dedicated global owner page at `/assistant/setup`, or
|
|
10
|
+
`/system/assistant/setup` when the Admin helpers receive `mount: '/system'`.
|
|
11
|
+
The literal `me.is_superuser === true` requirement applies before lazy loading,
|
|
12
|
+
in grouped and ordinary menu entries, landing selection, direct component
|
|
13
|
+
mounting and every action. Permission-driven `admin`, `manage_settings`,
|
|
14
|
+
Assistant permissions and member/group grants cannot satisfy it. The server
|
|
15
|
+
also rejects confined ApiKey/GroupScopedToken sessions and enforces person
|
|
16
|
+
ownership; the client does not invent a broader per-user-key ban.
|
|
17
|
+
|
|
18
|
+
The basic section shows deployment readiness, exact provider/model/key
|
|
19
|
+
selection, Automatic — latest Sonnet or an explicit manual pin, credential source and optional server hint, blank replacement input,
|
|
20
|
+
Check and save key, Check current key and enable/disable. A configured key and
|
|
21
|
+
an enabled switch do not prove readiness. `route.ready` describes configuration,
|
|
22
|
+
not current provider health. Unknown routes remain unknown: a missing
|
|
23
|
+
credential can cause the backend to omit the entire route. Only an explicit
|
|
24
|
+
`handler` route points to the Platform credential section. Bedrock uses AWS
|
|
25
|
+
identity from deployment. Assistant, Platform and AWS credentials never
|
|
26
|
+
substitute for one another. Missing Assistant/realtime applications are also
|
|
27
|
+
reported. Runtime model identifiers preserve provider punctuation, including
|
|
28
|
+
Bedrock colons; only a manual pin uses the backend's restricted pin syntax.
|
|
29
|
+
|
|
30
|
+
Advanced native details separate Platform credentials, deployed policy/safety,
|
|
31
|
+
remote access/connections and incident triage. Policy activation acknowledges
|
|
32
|
+
the deployed policy on this node, does not edit it and never establishes
|
|
33
|
+
fleet-wide agreement. Static, database and effective emergency stops are
|
|
34
|
+
separate; only the database switch is writable. Activation and breaker reset
|
|
35
|
+
cannot release a stop.
|
|
36
|
+
|
|
37
|
+
Model selection controls the protected runtime selection only when the backend
|
|
38
|
+
returns a valid capability for the explicit Anthropic `auto:sonnet` policy.
|
|
39
|
+
Fixed Anthropic policies, Bedrock and unavailable policies remain read-only.
|
|
40
|
+
A deployment pin permits an owner manual override, but Automatic remains
|
|
41
|
+
unavailable until deployment removes that pin. Mode is authoritative even when
|
|
42
|
+
a fixed route retains an inert legacy `selected` value.
|
|
43
|
+
|
|
44
|
+
The exact resolved runtime identifier (`model.effective`) and source are
|
|
45
|
+
separate from the selection draft and `route.ready`. Advanced → Deployed policy
|
|
46
|
+
and safety contains the raw policy model and admission diagnostic. The additive
|
|
47
|
+
`route.can_invoke` reports admission to the guarded request path: a cold
|
|
48
|
+
automatic catalogue can admit a request while configuration readiness remains
|
|
49
|
+
false. It does not prove that a usable model or healthy provider is ready.
|
|
50
|
+
|
|
51
|
+
Refresh catalogue is an explicit backend request; only the backend contacts the
|
|
52
|
+
provider. The browser never decides which model is newest. A refresh announces
|
|
53
|
+
success only for `model.refresh.ok === true`, including when a manual pin
|
|
54
|
+
remains selected. Failed/throttled/in-flight attempts may retain a fresh or
|
|
55
|
+
stale cached resolution; the page reports its exact freshness, last successful
|
|
56
|
+
fetch and attempt without claiming a newer model. Passive reads neither refresh
|
|
57
|
+
the catalogue nor repeat the preceding explicit refresh outcome.
|
|
58
|
+
|
|
59
|
+
Check public discovery explicitly probes this installation's public address
|
|
60
|
+
(server cache: 60 seconds). Ordinary page reads trigger neither probe.
|
|
61
|
+
|
|
62
|
+
Both credential drafts and all setup operations stay imperative and page-local.
|
|
63
|
+
There is no autosave, model definition, Query/Mutation entry, browser
|
|
64
|
+
persistence, export, URL value or secret-bearing mock history. The backend
|
|
65
|
+
checks a replacement before encrypted storage; a candidate-only verification
|
|
66
|
+
never updates the stored-key check record. Successful credential saves and
|
|
67
|
+
clears empty the relevant draft. Clearing protected storage may reveal a
|
|
68
|
+
deployment fallback, so the returned source remains authoritative. Fixed
|
|
69
|
+
backend pre-write rejection/unreachable messages map to safe actionable copy;
|
|
70
|
+
unknown failures refresh authoritative state and report an uncertain outcome
|
|
71
|
+
without replaying the operation.
|
|
72
|
+
|
|
73
|
+
One operation/confirmation lock, AbortSignal and live owner/session guard cover
|
|
74
|
+
loads, confirmations, auth waits and late responses. Leaving the page,
|
|
75
|
+
revocation, logout or explicit session replacement discards drafts and pending
|
|
76
|
+
work. Ordinary same-tab token renewal preserves a draft. Cross-tab auth-storage
|
|
77
|
+
changes conservatively discard it: the shared auth API cannot distinguish
|
|
78
|
+
renewal from same-person replacement across tabs. A 440 uses the existing
|
|
79
|
+
fresh-auth UI after clearing credential drafts; even successful reauthentication
|
|
80
|
+
requires explicit re-entry/retry. No secret is silently replayed. Confirmation
|
|
81
|
+
is page-local, focuses Cancel, and ends with the page/session scope.
|
|
82
|
+
|
|
83
|
+
Protocol helpers are exported from `portal-mojo/admin/assistant`:
|
|
84
|
+
`getAssistantSetup(options, probe?)`, `mutateAssistantSetup(action, options)`,
|
|
85
|
+
`assistantSetupSave(state, changes)`, `projectAssistantSetup`,
|
|
86
|
+
`assistantSetupReadiness`, and `assistantSetupCredentialRefusal`. Options accept
|
|
87
|
+
`signal` and a `beforeSend` validity guard; mutation helpers enforce same-origin
|
|
88
|
+
before and after auth preflight and use the existing `mojoCall` envelope boundary.
|
|
89
|
+
`schema_version: 2` responses are positively projected with bounds of 200
|
|
90
|
+
model choices/connections/request aggregates and 100 breaker rows. Runtime IDs
|
|
91
|
+
preserve provider punctuation; only manual pins use the backend's restricted
|
|
92
|
+
81-character lowercase alphanumeric/dot/hyphen syntax.
|
|
93
|
+
|
|
94
|
+
The additive wire fields live directly under `model`: `mode` (`auto`, `pinned`,
|
|
95
|
+
`fixed`), `editable`, `policy_model`, `restriction` (empty, `fixed_policy`,
|
|
96
|
+
`provider_unsupported`, `deployment_pin`, `policy_unavailable`), `discovery`
|
|
97
|
+
(`status`: `fresh`, `stale`, `unavailable`, `not_applicable`; nullable ISO
|
|
98
|
+
`fetched_at`, `attempted_at`, `expires_at`, `max_stale_at`; safe `error_code`),
|
|
99
|
+
and `refresh` (`attempted`, nullable boolean `ok`, safe `code`). The client
|
|
100
|
+
positively projects the complete valid set into optional `model.capability`.
|
|
101
|
+
Absent, malformed or unknown capabilities keep runtime facts visible, with
|
|
102
|
+
upgrade/read-only copy and no enabled selection action. No latest ID ships in
|
|
103
|
+
the production UI; returned bounded choices supply the datalist.
|
|
104
|
+
|
|
105
|
+
| Request | Exact body / query |
|
|
106
|
+
|---|---|
|
|
107
|
+
| Passive GET `/api/account/admin/assistant` | No probe parameters |
|
|
108
|
+
| Explicit catalogue / discovery GET | `refresh=models` / `check=discovery` |
|
|
109
|
+
| Save POST | `{action:'save',enabled:boolean,model?:string}` plus only intended optional `api_key`, `clear_api_key`, `handler_api_key`, `clear_handler_api_key`, `mcp_enabled`, `emergency_stop`, `autonomous_triage` |
|
|
110
|
+
| Model selection POST | Exactly `{action:'set_model_selection',mode:'auto'}` (no `model`) or `{action:'set_model_selection',mode:'pinned',model:ID}`; `saved:boolean` |
|
|
111
|
+
| Verify POST | `{action:'verify',target:'assistant'|'handler',api_key?}`; omitted candidate checks that exact stored credential |
|
|
112
|
+
| Policy POST | Exactly `{action:'activate_policy'}`; `activated:boolean` |
|
|
113
|
+
| Breaker POST | `{action:'reset_breaker',provider?:'anthropic'|'bedrock'}`; `reset:number` |
|
|
114
|
+
| Historical triage POST | Exactly `{action:'historical_triage',before:ISO,limit:1..100}`; `queued:number` |
|
|
115
|
+
| Disconnect POST | Exactly `{action:'revoke_grant',grant_id:positiveInteger}` or `{action:'revoke_all_grants'}`; `revoked:number` |
|
|
116
|
+
|
|
117
|
+
Every mutation returns fresh `state` plus the action result. Verification may
|
|
118
|
+
return `result.ok:false` in a successful envelope; that remains a failed check.
|
|
119
|
+
Save always sends authoritative `enabled`. With a valid capability it omits
|
|
120
|
+
`model` and cannot reset runtime selection; only the dedicated selection action
|
|
121
|
+
can change it. Capability-absent older schema-2 servers retain the required
|
|
122
|
+
`enabled`/legacy `model` baseline because they write both even when omitted.
|
|
123
|
+
On delegated `auto:sonnet` routes, new servers reject a differing legacy model
|
|
124
|
+
echo, preventing stale clients from reverting the active choice. Fixed policies,
|
|
125
|
+
Bedrock and unavailable-policy routes retain an inert legacy writer; these
|
|
126
|
+
values cannot change their deployed runtime model. Model actions carry no
|
|
127
|
+
enabled/key/stop/MCP/triage fields, and all selection drafts reset from each
|
|
128
|
+
authoritative response. Optional section switches are not
|
|
129
|
+
echoed during unrelated saves, and effective stop is never used as the database
|
|
130
|
+
stop. Replacement and clear are separate operations. The server retains its
|
|
131
|
+
600-second fresh-auth, protected settings, auditing and same-origin checks;
|
|
132
|
+
generic Settings still cannot write the Assistant-owned protected keys.
|
|
133
|
+
|
|
134
|
+
Remote access off pauses existing grants without revoking them. The connection
|
|
135
|
+
count remains the full server count when rows are capped at 200. Tools, Full API
|
|
136
|
+
and combined grants are labeled separately; Full API carries the signed-in
|
|
137
|
+
user's API authority. Disconnect all spans both resource paths for every user.
|
|
138
|
+
Returned addresses are inert text/read-only select-to-copy inputs. Triage
|
|
139
|
+
activation establishes the no-history watermark; historical processing requires
|
|
140
|
+
an explicit cutoff, bounded limit and confirmation.
|
|
141
|
+
|
|
142
|
+
The mock-only Assistant showcase adds Setup with explicit fake owner/denied
|
|
143
|
+
permission-admin buttons, a one-shot fresh-auth challenge button, and ready, missing policy/key, handler, Bedrock, static
|
|
144
|
+
stop, rejected key, discovery failure, bounded-grants and deployment-fallback
|
|
145
|
+
scenarios. Model scenarios include manual pins, fixed policy, deployment pin
|
|
146
|
+
(including an owner override), fresh/stale refresh failure, unavailable
|
|
147
|
+
resolution, throttled/in-flight refresh, old-server capability absence and
|
|
148
|
+
malformed capability. `fixture-sonnet-2099-01` and `fixture-sonnet-2099-02` are
|
|
149
|
+
visibly fake future IDs; explicit catalogue refresh advances the fake catalogue,
|
|
150
|
+
preserves manual pins, and returning to Automatic adopts the successor. Seeded `assistant.owner@nativemojo.com` is a literal superuser;
|
|
151
|
+
`assistant.wildcard@nativemojo.com` has permission-driven admin only. Both use
|
|
152
|
+
fake password `mojo`. No real credentials or deployment changes belong in demos.
|
|
153
|
+
`verify:admin-assistant-setup` covers wire contracts, owner navigation/admission,
|
|
154
|
+
projections and mounted auth/draft/confirmation/fresh-auth/transport/cache
|
|
155
|
+
lifecycle; it is wired into `verify:release`. Browser checks separately establish
|
|
156
|
+
both-theme layout, native details, keyboard controls and console behavior.
|
|
6
157
|
|
|
7
158
|
## Conversation transport
|
|
8
159
|
|
|
@@ -26,6 +26,17 @@ use `basePath: ''`; its labeled routes become visible child links rather than
|
|
|
26
26
|
claiming `/`. Prefixed sections receive an index redirect to the first route
|
|
27
27
|
the current operator can see.
|
|
28
28
|
|
|
29
|
+
## Literal-owner routes
|
|
30
|
+
|
|
31
|
+
`AdminRoute.requireSuperuser?: boolean` is an additive opt-in gate. It requires
|
|
32
|
+
literal `me.is_superuser === true` before a lazy page can load and during
|
|
33
|
+
section/mount landing selection. `adminSectionsMenu` carries it into grouped
|
|
34
|
+
and ordinary `MenuItem.requireSuperuser` entries. Permission-driven admin and
|
|
35
|
+
group grants never satisfy it; existing permission semantics remain unchanged.
|
|
36
|
+
Built-in Assistant Setup uses this gate and additionally checks live ownership
|
|
37
|
+
and session lifetime within the component/actions. Toolkit consumers can opt
|
|
38
|
+
into the same route/menu guard without changing other routes.
|
|
39
|
+
|
|
29
40
|
## Group API keys
|
|
30
41
|
|
|
31
42
|
```tsx
|
|
@@ -195,3 +206,30 @@ See [Admin modal policy](admin-modals.md) for header actions, content-only
|
|
|
195
206
|
sections, supported lifecycle fields and retained irreversible exceptions.
|
|
196
207
|
Group API keys and webhook subscriptions deactivate/reactivate; their built-in
|
|
197
208
|
Delete controls are removed. Reveal, secret rotation and cache boundaries remain.
|
|
209
|
+
|
|
210
|
+
## Protected ACME consumer purpose
|
|
211
|
+
|
|
212
|
+
Literal deployment operators can open **Create ACME consumer key** from the
|
|
213
|
+
existing fixed-Group or cross-Group API-key inventory. This lazy form resolves
|
|
214
|
+
the selected original hub Group through the private shared-validation recipient
|
|
215
|
+
endpoint. It displays the actual active Group name/UUID, the named ACME validation
|
|
216
|
+
consumer purpose and the fixed `dnsman_acme_federation` consequence. A tenant or
|
|
217
|
+
acting user cannot substitute for the original recipient. It has no freeform
|
|
218
|
+
permission or JSON input. The server rechecks Group activity, expected label and
|
|
219
|
+
protected grant at issuance and rejects key-backed sessions.
|
|
220
|
+
|
|
221
|
+
Issue is separately confirmed, single-flight and session-bound. Its response is
|
|
222
|
+
split before presentation: safe key metadata may be displayed; the transient
|
|
223
|
+
token stays outside Query/Mutation caches, URL/history and storage. Closing the
|
|
224
|
+
native token dialog drops that display. The existing explicit, audited
|
|
225
|
+
`/api/group/apikey/<id>?graph=token` reveal remains the recovery route. A timeout
|
|
226
|
+
may follow successful issuance: inspect the exact Group's recent inventory and
|
|
227
|
+
use audited reveal before creating another successor. The form blocks automatic
|
|
228
|
+
reissue and never retries after fresh authentication.
|
|
229
|
+
|
|
230
|
+
Create a replacement, enter it normally in the receiving deployment's protected
|
|
231
|
+
connection form, Preview/Publish, Apply and verify every expected node. Only then
|
|
232
|
+
explicitly review/deactivate the old hub key using existing key controls. This
|
|
233
|
+
form neither rotates nor retires keys, grants allocation trust, activates hub
|
|
234
|
+
sharing or asserts cross-deployment verification. Existing in-place key rotation
|
|
235
|
+
semantics remain unchanged and can invalidate the previous token immediately.
|
|
@@ -120,3 +120,163 @@ npm run verify:admin-dns-records
|
|
|
120
120
|
|
|
121
121
|
Live verification is read-only. Do not request or revoke a real certificate
|
|
122
122
|
without separate operator authorization.
|
|
123
|
+
|
|
124
|
+
## Shared validation setup
|
|
125
|
+
|
|
126
|
+
Use **Domains → Shared validation setup**, or **Set up shared validation** in a
|
|
127
|
+
group-managed Domain or Certificate header menu. Domain **Validation** and
|
|
128
|
+
Certificate **Delegation** show the same read-only facts. No new route or sidebar
|
|
129
|
+
resource is added. The flow never reads certificate material.
|
|
130
|
+
|
|
131
|
+
1. Select an authorized existing local Domain, or an eligible group and exact
|
|
132
|
+
apex name. Group selection uses `/api/dnsman/delegation/group-choice`, bounded
|
|
133
|
+
`search/start/size` and explicit `?id=` hydration. Product active-group context
|
|
134
|
+
and credential group choices do not authorize shared setup.
|
|
135
|
+
2. Enter the existing public allocation target supplied by its controller and
|
|
136
|
+
**Inspect plan**. Inspection creates no connection or reference.
|
|
137
|
+
3. **Prepare connection** and confirm the displayed domain/profile/target.
|
|
138
|
+
Preparation pauses direct local validation and renewal until authorization
|
|
139
|
+
and checking finish. Existing valid certificate material remains available.
|
|
140
|
+
4. **Download request** saves `shared-validation-request.json`. Send it to the
|
|
141
|
+
allocation controller using your normal coordination channel. **Share request**
|
|
142
|
+
uses native file sharing when supported; **Copy request** is optional. Download
|
|
143
|
+
stays available after copy/share denial or cancellation. The canonical file is
|
|
144
|
+
at most 2048 UTF-8 bytes and has exactly `version:1`, `consumer_project_uuid`,
|
|
145
|
+
`client_ref`, `domain`, `allocation_ref`, with no wrapper, key, token or scope.
|
|
146
|
+
5. The controller opens their deployment’s **Domains → Shared validation setup →
|
|
147
|
+
Controller review**, checks access and uses **Import request**. There is no JSON
|
|
148
|
+
editor or controller URL. Empty, oversized, malformed, noncanonical or extra-field
|
|
149
|
+
files are refused before installation. Import alone grants nothing. The named
|
|
150
|
+
public fields fill the exact domain query; **Find allocations**, page if needed
|
|
151
|
+
and select the exact existing target. Only a matching request and resolved active
|
|
152
|
+
exact recipient enable **Review grant**, then **Allow issuance** after consent
|
|
153
|
+
names both apex and wildcard authority. No allocation is created.
|
|
154
|
+
6. Back in the project, **Refresh**, **Connect approved validation**, then
|
|
155
|
+
**Check validation**. These are separate deliberate actions. Check requires
|
|
156
|
+
the approved existing one-hop `_acme-challenge.<apex>` CNAME.
|
|
157
|
+
7. **Request wildcard certificate** issues this deployment's own apex-plus-
|
|
158
|
+
wildcard certificate. Existing valid exact-profile certificates remain in
|
|
159
|
+
place; queued work stays queued and due renewal reuses its lineage. Watch
|
|
160
|
+
the local certificate and separate renewal status, or Refresh after timeout.
|
|
161
|
+
|
|
162
|
+
Only global DNS managers (`sys.manage_dns | sys.security`) see local mutation
|
|
163
|
+
controls, and every action also requires the backend's current per-target flag.
|
|
164
|
+
Controller operations additionally require v2 `shared_validation` and
|
|
165
|
+
`can_manage_trust`, then exact-allocation authority. A human controller can have
|
|
166
|
+
`can_consume:false`; local project setup uses the server-held project identity
|
|
167
|
+
independently. Ordinary DNS managers cannot grant themselves trust. Groupless
|
|
168
|
+
house domains are read-only and ineligible in this rollout; direct operation
|
|
169
|
+
remains available and Portal never assigns a group automatically.
|
|
170
|
+
|
|
171
|
+
### Local API and safe state
|
|
172
|
+
|
|
173
|
+
| Method | Local route under `/api/dnsman` | Input |
|
|
174
|
+
|---|---|---|
|
|
175
|
+
| GET | `delegation/plan` | `{domain}` or `{group,name}`, optional `allocation_ref` |
|
|
176
|
+
| POST | `delegation/connect` | Same target plus `allocation_ref`, optional explicit `restart:true` |
|
|
177
|
+
| POST | `delegation/check` | `{delegation:<local id>}` |
|
|
178
|
+
| POST | `delegation/request` | `{delegation:<local id>}`; no custom SANs, force or keys |
|
|
179
|
+
| GET | `delegation/group-choice` | `id` or bounded `search/start/size` |
|
|
180
|
+
|
|
181
|
+
All setup actions return Readiness v1. Portal strictly projects only public
|
|
182
|
+
metadata and validates version, selected identity, source/target, fixed profile,
|
|
183
|
+
booleans and enums. Expected 409s can include the same safe readiness DTO.
|
|
184
|
+
Unknown containers and provider error text are discarded before state. Plans,
|
|
185
|
+
descriptors and controller identities are modal-local; no draft is persisted or
|
|
186
|
+
written to URLs, diagnostics or logs. Writes are imperative and non-retrying,
|
|
187
|
+
freeze the scope, recheck auth/session/permission before send, and reject late
|
|
188
|
+
responses after scope loss. After every attempted write, safe Domain,
|
|
189
|
+
Certificate and legacy delegation caches are invalidated and plan/trust is
|
|
190
|
+
refreshed. Ambiguous results require successful Refresh before another write.
|
|
191
|
+
A 440 prompts authentication but never automatically repeats the operation.
|
|
192
|
+
Every explicit session replacement, including the same user signing in again,
|
|
193
|
+
clears controller capabilities, recipients and participant facts. Check controller
|
|
194
|
+
access and select an authorized allocation again. A new grant also requires a matching imported request and freshly resolved active recipient.
|
|
195
|
+
Closing a view cannot cancel a write already submitted.
|
|
196
|
+
|
|
197
|
+
Controller POSTs use only the local `/api/dnsman/acme` endpoints:
|
|
198
|
+
`capabilities {}`, `allocation/list {domain,cursor?}`,
|
|
199
|
+
`trust/list {allocation_ref,cursor?}`,
|
|
200
|
+
`trust/recipient {allocation_ref,consumer_project_uuid}`,
|
|
201
|
+
`trust/grant {connection_request}` and
|
|
202
|
+
`trust/revoke {allocation_ref,participant_ref}`. Each page contains at most 20
|
|
203
|
+
rows. Only a capability-approved controller probes the allocation/trust routes;
|
|
204
|
+
there is no arbitrary project directory, remote hub call, key provisioning or
|
|
205
|
+
consumer/status call from a human JWT. Recipient and allocation authorization
|
|
206
|
+
are repeated server-side on every operation.
|
|
207
|
+
|
|
208
|
+
### Operator setup and mixed versions
|
|
209
|
+
|
|
210
|
+
If the local plan says the hub is unconfigured or misconfigured, a deployment
|
|
211
|
+
operator uses the existing server configuration delivery to set
|
|
212
|
+
`DNSMAN_ACME_HUB_URL` to the already-used Maestro hub and
|
|
213
|
+
`DNSMAN_ACME_HUB_API_KEY` to the already-provisioned protected project key in
|
|
214
|
+
Django settings, normally `VAR_ROOT/django.conf`. Upgrade the hub first, then
|
|
215
|
+
project API and every certificate worker; drain/restart old issuance workers
|
|
216
|
+
before shared connections are accepted. Restart application and worker
|
|
217
|
+
processes and **Refresh Portal**. A responsive API does not prove that workers
|
|
218
|
+
were restarted; worker version is unknown unless authoritative telemetry exists.
|
|
219
|
+
These settings are static deployment configuration, never DB Setting overrides,
|
|
220
|
+
browser fields, arbitrary per-site URLs or values copied into descriptors.
|
|
221
|
+
|
|
222
|
+
404/405 and unsupported new versions disable only shared setup; existing strict
|
|
223
|
+
DNS config, direct-provider and legacy single-consumer certificate paths retain
|
|
224
|
+
their contracts. 401/403 report access refusal instead of suggesting an upgrade.
|
|
225
|
+
Disabled sharing, unconfigured/auth-rejected/unavailable hubs and unknown proof
|
|
226
|
+
never display setup as complete. Portal does not bypass backend activation.
|
|
227
|
+
|
|
228
|
+
### Repair and revocation
|
|
229
|
+
|
|
230
|
+
ACME validation and traffic routing are separate. The validation CNAME does not
|
|
231
|
+
route apex/www/API/app traffic. Follow the deployment's separate A/AAAA/CNAME
|
|
232
|
+
traffic instructions. Missing, changed or chained validation proof shows the
|
|
233
|
+
expected and bounded observed target and its check time. Ask the domain owner
|
|
234
|
+
to restore the approved one-hop route after checking other consumers. Portal
|
|
235
|
+
does not replace/remove that CNAME or rotate the allocation as a default repair.
|
|
236
|
+
|
|
237
|
+
Controller maintenance starts cold with **Check controller access**, an **Exact
|
|
238
|
+
domain** and **Find allocations**. Native choices show target and owner UUID.
|
|
239
|
+
**Next allocation page** / **First allocation page** and **Next project page** /
|
|
240
|
+
**First project page** navigate bounded 20-row pages. Select an allocation to
|
|
241
|
+
inspect participants, role, state, exact scope and revoked time. No request file
|
|
242
|
+
or recipient lookup is needed for this path. An imported inactive consumer can
|
|
243
|
+
fail recipient lookup while participant inspection, revoke and cleanup remain
|
|
244
|
+
available. Owner participants cannot be revoked. **Refresh trust** checks current
|
|
245
|
+
capabilities; an unsuccessful reconciliation blocks mutation until refresh succeeds.
|
|
246
|
+
|
|
247
|
+
Controller revocation stops future DNS-01 validation for that project. Already-
|
|
248
|
+
issued certificates remain valid until expiry or separate certificate revocation,
|
|
249
|
+
and other trusted projects keep working. A 503 may occur after revocation was
|
|
250
|
+
persisted; refreshed trust can say revoked while DNS cleanup remains unconfirmed.
|
|
251
|
+
Retrying cleanup never regrants the reference. A revoked reference cannot be
|
|
252
|
+
revived: the project must explicitly confirm **Prepare fresh request**, keep
|
|
253
|
+
the existing target, and obtain a new exact controller grant.
|
|
254
|
+
|
|
255
|
+
A valid local certificate with blocked/failed/retrying renewal is shown as
|
|
256
|
+
“valid until …; renewal needs attention.” It is not labeled expired or revoked
|
|
257
|
+
as a repair. Material custody is API-node evidence, not proof that any serving
|
|
258
|
+
host installed that certificate. Shared pending/broken/revoked routing never
|
|
259
|
+
permits fallback TXT writes through the direct provider. Private keys stay in
|
|
260
|
+
each deployment.
|
|
261
|
+
|
|
262
|
+
The mock showcase includes deterministic controller-maintenance pages and an inactive consumer, plus the complete project/controller handshake, viewer,
|
|
263
|
+
revoked, pending/changed/chained DNS, disconnected/unconfigured/disabled hub,
|
|
264
|
+
older API, failed renewal and 390px embedded-content scenarios. Scenario changes
|
|
265
|
+
reset mock shared state; identity changes preserve it. Leaving the demo restores
|
|
266
|
+
its default mock identity and scenario. `verify:admin-dns-shared-validation`
|
|
267
|
+
runs API/projection and React StrictMode mounted contracts. Real browser proof
|
|
268
|
+
remains required for focus, native-dialog stacking, clipboard and both themes.
|
|
269
|
+
|
|
270
|
+
Owner and consumer project identities preserve existing lowercase16hex Group
|
|
271
|
+
IDs as well as the previously supported32hex and canonical UUID forms. They
|
|
272
|
+
are compared exactly and never padded, regenerated or rewritten. Client and
|
|
273
|
+
participant references retain their strict UUID validation; a short project ID
|
|
274
|
+
cannot stand in for either reference.
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
Shared setup prerequisites now link literal deployment operators to the actual
|
|
278
|
+
mount-aware Fleet shared-validation connection topic. It owns named approved
|
|
279
|
+
profiles, write-only protected keys, expected/observed identity and revision-bound
|
|
280
|
+
Preview/Publish/Apply. Ordinary DNS managers receive a concrete domain, next
|
|
281
|
+
action and checked-time handoff with no private inputs or private API background
|
|
282
|
+
calls. This route does not perform the protected hub activation ceremony.
|
package/docs/admin-dns.md
CHANGED
|
@@ -84,3 +84,19 @@ See [Admin modal policy](admin-modals.md) for header actions, content-only
|
|
|
84
84
|
sections, supported lifecycle fields and retained irreversible exceptions.
|
|
85
85
|
Provider credentials retire/reactivate through `is_active`, keeping history;
|
|
86
86
|
rotation remains write-only and imperative. Built-in credential Delete is absent.
|
|
87
|
+
|
|
88
|
+
## Shared wildcard validation
|
|
89
|
+
|
|
90
|
+
The existing Domains header offers **Shared validation setup** to global DNS
|
|
91
|
+
managers even when server setup needs an operator. Domain detail includes
|
|
92
|
+
read-only **Validation**; its header action and Certificate Delegation compose
|
|
93
|
+
the same focused flow. See [the human walkthrough and exact
|
|
94
|
+
contracts](admin-dns-certificates.md#shared-validation-setup).
|
|
95
|
+
|
|
96
|
+
Shared setup uses independent Readiness v1/hub v2 adapters. It never changes the
|
|
97
|
+
strict legacy `/config` response contract. A controller grant is explicit
|
|
98
|
+
apex/wildcard certificate issuance authority; local DNS management alone cannot
|
|
99
|
+
supply it. Only public five-field connection requests are copied. No private
|
|
100
|
+
key, PEM, DNS credential or protected hub key is requested, read, persisted or
|
|
101
|
+
logged. Deployment operators deliver static hub settings server-side and restart
|
|
102
|
+
API/workers. Validation CNAME routing remains separate from traffic routing.
|
|
@@ -7,8 +7,9 @@ page checks `is_superuser === true` before fetching. Backend authority remains
|
|
|
7
7
|
mandatory, including rejection of diagnostic/key-backed sessions and fresh auth.
|
|
8
8
|
|
|
9
9
|
Applications register their schema in django-mojo. The page renders the returned
|
|
10
|
-
section, label, description, default, type and restart requirement;
|
|
11
|
-
|
|
10
|
+
section, label, description, default, type and restart requirement; application schemas remain server-owned. The three managed shared-validation
|
|
11
|
+
connection fields route to the dedicated topic below, rather than appearing as
|
|
12
|
+
independently editable generic fields. Each field defaults to Keep current value. Set value
|
|
12
13
|
and Remove published override are explicit actions. Clearing falls back to base
|
|
13
14
|
configuration/default; it does not promise erasure of a bootstrap secret.
|
|
14
15
|
|
|
@@ -48,3 +49,98 @@ example. Mock Portal uses representative registered settings and an offline node
|
|
|
48
49
|
Django receives this page only after a canonical Portal artifact is built and
|
|
49
50
|
vendored; follow `docs/admin-artifact.md` and the Django vendor tool. Ordinary
|
|
50
51
|
Vite build output is not the canonical artifact.
|
|
52
|
+
|
|
53
|
+
## Shared validation connection
|
|
54
|
+
|
|
55
|
+
Operations → Fleet Configuration → Shared validation connection is a private, lazy
|
|
56
|
+
route. It requires a current literal superuser; the server additionally requires
|
|
57
|
+
an active interactive session, same-origin writes and fresh authentication.
|
|
58
|
+
Key-backed sessions are rejected by the server even when their user is an owner.
|
|
59
|
+
|
|
60
|
+
On the validation hub, update every expected node using the existing Deployments
|
|
61
|
+
controls, then use **Enable shared validation** once. The compact hub section is
|
|
62
|
+
independent of consumer connection configuration and uses the same Portal login,
|
|
63
|
+
fresh authentication and native confirmation as the existing page. No separate
|
|
64
|
+
operator service, login or wizard is required. Missing or incompatible deployment
|
|
65
|
+
proof shows the ordinary prerequisite instead of an enabled action. Each issuer
|
|
66
|
+
keeps its own ACME account, certificates and private keys; allocation trust still
|
|
67
|
+
requires explicit approval in the DNS setup screen. Renewal remains automatic.
|
|
68
|
+
|
|
69
|
+
`GET /api/account/admin/fleet/shared-validation/hub` returns
|
|
70
|
+
`{version:1, enabled, configured, deployment_uuid, can_enable, reason}`.
|
|
71
|
+
The deployment UUID is canonical lowercase with hyphens, unlike consumer project
|
|
72
|
+
UUIDs. `POST` takes only `{deployment_uuid}` after confirmation. The backend
|
|
73
|
+
rechecks the complete deployed roster and framework version atomically before
|
|
74
|
+
enabling. A stale deployment, failed read or fresh-auth refusal requires Refresh
|
|
75
|
+
and another deliberate review; mutations are never replayed. Keep the compatible
|
|
76
|
+
framework on every node after enabling sharing.
|
|
77
|
+
|
|
78
|
+
The panel consumes the private `/api/account/admin/fleet/shared-validation`
|
|
79
|
+
contract. Choose a named approved hub profile, inspect its exact origin and
|
|
80
|
+
original project UUID, then Keep, Replace or Disable the connection. Replacement
|
|
81
|
+
is a normal write-only password field; blank preserves the existing credential.
|
|
82
|
+
The approved catalog fixes the origin. Arbitrary URLs and raw JSON are not inputs.
|
|
83
|
+
|
|
84
|
+
Project identity fields also accept existing lowercase16hex Group IDs, preserving
|
|
85
|
+
the exact value through profiles, observations and protected key issuance. Fleet
|
|
86
|
+
revisions/operation IDs remain32hex and deployment IDs remain canonical UUIDs.
|
|
87
|
+
The legacy identity showcase fixture changes wire data only; no Group identity
|
|
88
|
+
is migrated or rewritten.
|
|
89
|
+
|
|
90
|
+
Preview probes the candidate without saving it. Publication has a separate
|
|
91
|
+
confirmation, frozen against the preview and auth session. Publishing revalidates
|
|
92
|
+
the catalog and expected revision; it does not Apply. Apply has another
|
|
93
|
+
confirmation and targets the exact current revision. Every expected node must
|
|
94
|
+
report installed, restarted and combined request-service/job-engine/scheduler
|
|
95
|
+
health at that revision and the expected topic profile/project identity. Offline,
|
|
96
|
+
draining, stale, partial and missing-node results remain unconfirmed. The UI
|
|
97
|
+
polls at most120 observations and offers deliberate Refresh afterward. Verified
|
|
98
|
+
connection identity with `sharing_ready=false` still needs sharing enabled on the
|
|
99
|
+
approved hub. Refresh the connection after enabling it there.
|
|
100
|
+
|
|
101
|
+
Create the replacement on the approved hub with the named **ACME validation
|
|
102
|
+
consumer** key form. Preview/Publish, Apply, verify every expected node, then
|
|
103
|
+
explicitly review and deactivate the old key in the hub inventory. Issuance,
|
|
104
|
+
publication and successful dispatch never retire keys. Disable masks the whole
|
|
105
|
+
connection tuple and base credential without deleting base settings or revoking
|
|
106
|
+
remote trust; retained/shared identities can make disabling ineligible.
|
|
107
|
+
|
|
108
|
+
Secrets remain in an uncontrolled mounted password input and a short-lived
|
|
109
|
+
imperative request draft. They never enter Query/Mutation caches, URL/history,
|
|
110
|
+
storage, receipts or logs. These new writes call `requestFreshAuth` without
|
|
111
|
+
replaying the attempted action; the existing generic Fleet helpers keep their
|
|
112
|
+
prior behavior. Auth/session change or unmount invalidates drafts and closes
|
|
113
|
+
owned confirmations. Double activation is single-flight. A409 revision/catalog
|
|
114
|
+
conflict or `configuration_busy` requires Refresh and a deliberate retry. An
|
|
115
|
+
uncertain publication or issuance may have persisted; read authoritative status
|
|
116
|
+
or exact Group inventory before another attempt.
|
|
117
|
+
|
|
118
|
+
Unavailable APIs, missing DNSMan/publisher/delegation/schema/enrollment or an empty
|
|
119
|
+
approved catalog render a concrete blocked state. Bootstrap supplies `admin_path`
|
|
120
|
+
and permission facts for existing legacy System Setup, Deployments, topology and
|
|
121
|
+
Fleet Scaling links. Links are same-origin and capability-gated. The backend's
|
|
122
|
+
semantic `capacity` hint maps to the actual registered `#/fleet` route. These
|
|
123
|
+
legacy destinations retain their protected confirmations, policy, release holds
|
|
124
|
+
and IaC restrictions. This React topic reuses those controls without a new
|
|
125
|
+
deployment or root authority service.
|
|
126
|
+
|
|
127
|
+
The Runtime settings showcase mounts the actual connection panel with central
|
|
128
|
+
mock scenarios and operator/ordinary-manager identities. The named
|
|
129
|
+
`verify:admin-shared-validation-config` gate includes private DTO/API and mounted
|
|
130
|
+
StrictMode contracts, and is included once by `verify:admin-contracts`. Browser
|
|
131
|
+
proof remains necessary for real native dialogs, keyboard/focus and390px in both
|
|
132
|
+
themes. Mock receipts are fixtures, never live configuration evidence.
|
|
133
|
+
|
|
134
|
+
The private form uses an inline-size container: fact labels stack above UUIDs and
|
|
135
|
+
revision values below420px of available content, including a narrow embedded
|
|
136
|
+
Admin host. The existing Admin sidebar's Collapse control supplies its normal
|
|
137
|
+
compact host at390px; the topic does not change global navigation behavior.
|
|
138
|
+
|
|
139
|
+
Every successful authoritative refresh invalidates a preview when revision,
|
|
140
|
+
catalog, profile, identity or credential facts change. Late preview/operation
|
|
141
|
+
responses cannot restore spent consent or overwrite a newer observation. After
|
|
142
|
+
the automatic observation limit, explicit Refresh re-observes the tracked exact
|
|
143
|
+
operation and resets the read budget; it never dispatches another Apply. Only
|
|
144
|
+
known healthy report/node statuses with no top-level or node error can turn the
|
|
145
|
+
combined proof green. Apply/read replies remain bound to their exact operation
|
|
146
|
+
ID and requested/tracked revision.
|
|
@@ -35,6 +35,18 @@ existing system permission gate and conditional queries. Parent, child, member
|
|
|
35
35
|
and user navigation opens native detail modals while keeping the directory
|
|
36
36
|
underneath.
|
|
37
37
|
|
|
38
|
+
The Sub-Groups section carries the "Administrators can create sub-groups"
|
|
39
|
+
switch for `sys.groups | sys.manage_groups` holders only; nobody else sees it.
|
|
40
|
+
It reads `metadata.protected.allow_member_subgroups === true` (anything else
|
|
41
|
+
is off) and changes it only through the django-mojo Group action
|
|
42
|
+
`POST /api/group/<id> {"allow_member_subgroups": true|false}`, which answers
|
|
43
|
+
`{"status": true, "allow_member_subgroups": <bool>}`. Never write
|
|
44
|
+
`metadata.protected` directly: that path refuses `manage_groups` admins. The
|
|
45
|
+
action needs django-mojo with #9126; the server refuses a caller without the
|
|
46
|
+
global grant with 403 and a non-boolean with 400. While on, people who manage
|
|
47
|
+
the group as members can create groups directly under it; the setting is not
|
|
48
|
+
inherited by the new groups, and turning it off leaves existing groups alone.
|
|
49
|
+
|
|
38
50
|
The group model and section code are adapted from the reference portal at
|
|
39
51
|
`v0.2.5` commit `93c7fdfeb3096d33010e72bd4483cf9ca6e3d6f5`. The source hashes
|
|
40
52
|
and corresponding package hashes are recorded in
|
|
@@ -62,6 +62,16 @@ per endpoint, so `UserDetail` and the fleet-wide tables share one cache.
|
|
|
62
62
|
|
|
63
63
|
## Action contracts
|
|
64
64
|
|
|
65
|
+
- **Set temporary password** is available in the user header menu and Security
|
|
66
|
+
section with `sys.users | sys.manage_users`. Confirmation identifies the user
|
|
67
|
+
and explains that their password is replaced and all sessions are revoked.
|
|
68
|
+
`POST /api/account/admin/user/password/temporary` sends only `{user: id}`
|
|
69
|
+
through `withFreshAuth` (440 prompts and retries once). The generated password
|
|
70
|
+
appears once in a copyable dialog; closing or losing permission removes it.
|
|
71
|
+
It never enters Query/Mutation cache, storage, or a toast. The server requires
|
|
72
|
+
a person session, restricts superuser recovery to superusers, and forces the
|
|
73
|
+
recipient to replace the password before completing sign-in. This uses the
|
|
74
|
+
existing django-mojo endpoint; no backend upgrade or new permission is added.
|
|
65
75
|
- Username changes use the `change_username` POST_SAVE_ACTION, not a direct
|
|
66
76
|
field save. Model saves/actions retry one fresh-auth 440 automatically;
|
|
67
77
|
combined `disable_totp` writes explicitly use `withFreshAuth`.
|
package/docs/admin-modals.md
CHANGED
|
@@ -135,3 +135,31 @@ browser interactions for all family bodies, both themes, desktop/narrow,
|
|
|
135
135
|
keyboard navigation and console checks. The lazy Showcase **Admin modal audit**
|
|
136
136
|
demo supplies long-title, rich/zero/dot badges, nested editor, lifecycle-cancel and
|
|
137
137
|
embedded-host cases. Existing ToastHost top-layer visibility work remains separate.
|
|
138
|
+
|
|
139
|
+
## Shared validation confirmations
|
|
140
|
+
|
|
141
|
+
The DNS shared-validation editor freezes the target group/domain, existing
|
|
142
|
+
allocation and session while an operation is pending. Grant additionally freezes
|
|
143
|
+
the imported request, active exact recipient UUID and client reference. Participant
|
|
144
|
+
revoke/cleanup freezes the selected current-page participant independently of any
|
|
145
|
+
request or recipient lookup; cleanup retry leaves the reference revoked.
|
|
146
|
+
Its owner AbortSignal closes only its confirmation on unmount, scope loss or
|
|
147
|
+
auth/session replacement; submitted writes can still persist. Escape/backdrop
|
|
148
|
+
and Close are unavailable while the outer operation is pending.
|
|
149
|
+
|
|
150
|
+
Prepare explains the pause of direct validation/renewal while valid material
|
|
151
|
+
remains available. Grant names the exact project and apex/wildcard issuance
|
|
152
|
+
authority and independent private-key custody. Revoke explains that future
|
|
153
|
+
validation stops, already-issued certificates remain valid and other consumers
|
|
154
|
+
keep working. Revoked references require a fresh, explicitly prepared request.
|
|
155
|
+
No confirmation is inferred from a copied descriptor. Fresh authentication
|
|
156
|
+
prompts without replay; every submitted result reconciles before another write.
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
The protected connection topic separately confirms Publish and Apply, naming
|
|
160
|
+
profile/project and exact revision consequences. The ACME consumer key form
|
|
161
|
+
confirms the current original Group name/UUID and fixed protected purpose before
|
|
162
|
+
issuance; its token display is transient and the existing audited reveal is
|
|
163
|
+
available for recovery. Every owned nested dialog receives the auth-owner abort
|
|
164
|
+
signal. Session replacement, scope loss and unmount close those dialogs; submitted
|
|
165
|
+
writes may still persist and are never replayed after fresh authentication.
|