portal-mojo 0.2.20 → 0.2.21
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/docs/README.md +7 -1
- package/docs/admin-deployments.md +201 -0
- package/docs/admin-dns-certificates.md +3 -3
- package/docs/admin-dns-domains.md +92 -0
- package/docs/admin-dns.md +4 -2
- package/docs/admin-edge.md +200 -196
- package/docs/admin-geolocation.md +100 -0
- package/docs/admin-maintenance.md +133 -0
- package/docs/admin-modals.md +17 -2
- package/docs/admin-operational-fleet.md +206 -0
- package/docs/admin-presentation.md +51 -0
- package/docs/admin-signin.md +12 -2
- package/docs/client.md +7 -0
- package/docs/combobox.md +18 -0
- package/docs/popover.md +5 -4
- package/package.json +1 -1
- package/src/admin/core/OperationsHelp.tsx +10 -0
- package/src/admin/core/index.ts +6 -4
- package/src/admin/core/route-context.ts +6 -0
- package/src/admin/deployments/ApiDeploymentDetail.tsx +58 -0
- package/src/admin/deployments/DeploymentsPage.tsx +73 -0
- package/src/admin/deployments/WebAppDeploySetup.tsx +49 -0
- package/src/admin/deployments/WebAppDeploymentDetail.tsx +59 -0
- package/src/admin/deployments/WebAppDetail.tsx +104 -0
- package/src/admin/deployments/WebAppEditDialog.tsx +70 -0
- package/src/admin/deployments/WebAppKeyDialog.tsx +25 -0
- package/src/admin/deployments/WebAppOnboardingDialog.tsx +217 -0
- package/src/admin/deployments/WebAppRollbackDialog.tsx +82 -0
- package/src/admin/deployments/WebAppUploadPanel.tsx +132 -0
- package/src/admin/deployments/api.ts +158 -0
- package/src/admin/deployments/authority-state.ts +9 -0
- package/src/admin/deployments/deployment-state.ts +13 -0
- package/src/admin/deployments/index.ts +4 -0
- package/src/admin/deployments/onboarding-state.ts +11 -0
- package/src/admin/deployments/permissions.ts +37 -0
- package/src/admin/deployments/receipts.ts +78 -0
- package/src/admin/deployments/sanitize.ts +73 -0
- package/src/admin/deployments/shared.tsx +39 -0
- package/src/admin/deployments/types.ts +238 -0
- package/src/admin/deployments/upload.ts +53 -0
- package/src/admin/deployments/useDeploymentObservation.ts +104 -0
- package/src/admin/dns/DomainDetail.tsx +10 -6
- package/src/admin/dns/DomainOnboardingContent.tsx +44 -0
- package/src/admin/dns/DomainOnboardingDialog.tsx +5 -24
- package/src/admin/dns/DomainPurchaseWizard.tsx +1 -1
- package/src/admin/dns/DomainRegisterExisting.tsx +63 -0
- package/src/admin/dns/DomainRegistrarSettings.tsx +52 -0
- package/src/admin/dns/DomainsPage.tsx +22 -13
- package/src/admin/dns/SharedValidationDialog.tsx +1 -1
- package/src/admin/dns/api.ts +4 -2
- package/src/admin/dns/domain-navigation.ts +16 -0
- package/src/admin/dns/registrar-api.ts +13 -0
- package/src/admin/domains/assistant.ts +5 -4
- package/src/admin/domains/communications.ts +10 -9
- package/src/admin/domains/identity.ts +8 -7
- package/src/admin/domains/infrastructure.ts +19 -13
- package/src/admin/domains/lazy-page.ts +6 -0
- package/src/admin/domains/observability.ts +6 -5
- package/src/admin/domains/operations.ts +22 -7
- package/src/admin/domains/security.ts +16 -15
- package/src/admin/edge/EdgeHelp.tsx +10 -0
- package/src/admin/edge/ServingReadiness.tsx +54 -0
- package/src/admin/edge/VhostDetail.tsx +145 -139
- package/src/admin/edge/VhostWizard.tsx +204 -115
- package/src/admin/edge/VhostsPage.tsx +27 -28
- package/src/admin/edge/api.ts +24 -10
- package/src/admin/edge/models.ts +4 -4
- package/src/admin/edge/serving-data.ts +78 -0
- package/src/admin/fleet/CapacityEditor.tsx +81 -0
- package/src/admin/fleet/CapacityInspector.tsx +19 -0
- package/src/admin/fleet/CapacityProgress.tsx +9 -0
- package/src/admin/fleet/FleetHelp.tsx +7 -0
- package/src/admin/fleet/FleetOverview.tsx +150 -0
- package/src/admin/fleet/FleetPage.tsx +11 -0
- package/src/admin/fleet/FleetWorkspace.tsx +82 -0
- package/src/admin/fleet/ScaleFleetDialog.tsx +169 -0
- package/src/admin/fleet/access.ts +22 -0
- package/src/admin/fleet/api.ts +77 -0
- package/src/admin/fleet/data.ts +148 -0
- package/src/admin/fleet/index.ts +8 -0
- package/src/admin/fleet/operations.ts +179 -0
- package/src/admin/fleet/standalone-data.ts +87 -0
- package/src/admin/fleet/types.ts +208 -0
- package/src/admin/geolocation/GeoLocationPage.tsx +171 -0
- package/src/admin/geolocation/data.ts +138 -0
- package/src/admin/geolocation/index.ts +3 -0
- package/src/admin/identity/members/GroupMembersPanel.tsx +2 -8
- package/src/admin/index.ts +8 -0
- package/src/admin/maintenance/MaintenanceDialogs.tsx +161 -0
- package/src/admin/maintenance/MaintenancePage.tsx +442 -0
- package/src/admin/maintenance/data.ts +486 -0
- package/src/admin/maintenance/index.ts +3 -0
- package/src/admin/maintenance/operations.ts +208 -0
- package/src/admin/public/infrastructure.ts +1 -0
- package/src/admin/public/operations.ts +3 -0
- package/src/admin/registry.ts +6 -2
- package/src/admin/settings/SettingDetail.tsx +7 -2
- package/src/admin/settings/SettingEditor.tsx +2 -1
- package/src/admin/settings/SettingsPage.tsx +3 -1
- package/src/admin/settings/model.ts +1 -0
- package/src/admin/signin/SigninPage.tsx +17 -3
- package/src/admin/signin/api.ts +2 -0
- package/src/charts/MetricsChartView.tsx +4 -11
- package/src/charts/MetricsMiniWidget.tsx +3 -15
- package/src/client/client.ts +6 -0
- package/src/client/deployments-mock.ts +375 -0
- package/src/client/domain-operations-mock.ts +37 -0
- package/src/client/geo-provider-mock.ts +82 -0
- package/src/client/maintenance-mock.ts +285 -0
- package/src/client/mock.ts +52 -10
- package/src/client/operational-fleet-mock.ts +279 -0
- package/src/client/operations-mock.ts +85 -0
- package/src/client/serving-mock.ts +22 -0
- package/src/styles/components/admin-deployments.css +35 -0
- package/src/styles/components/admin-domains.css +12 -0
- package/src/styles/components/admin-edge.css +125 -1
- package/src/styles/components/admin-geolocation.css +40 -0
- package/src/styles/components/admin-maintenance.css +127 -0
- package/src/styles/components/admin-operational-fleet.css +38 -0
- package/src/styles/components/admin-operations.css +9 -0
- package/src/styles/components/admin-signin.css +2 -0
- package/src/styles/components/combobox.css +12 -2
- package/src/styles/components/fleet-page.css +9 -0
- package/src/styles/index.css +7 -0
- package/src/ui/ComboBox.tsx +39 -8
- package/src/ui/FilterBar.tsx +3 -5
- package/src/ui/ModelTable.tsx +2 -8
- package/src/ui/Popover.tsx +15 -7
- package/src/ui/date/TimePicker.tsx +4 -14
- package/src/ui/image-editor/ImageEditor.tsx +4 -5
- package/src/ui/schema-form-core.tsx +3 -5
package/docs/README.md
CHANGED
|
@@ -14,11 +14,17 @@ everything: run the showcase (`npm run dev:showcase`) → **Develop → Componen
|
|
|
14
14
|
| [realtime.md](realtime.md) | Auth-challenged WebSocket lifecycle, heartbeat/backoff, refcounted topics, typed event projection, deterministic mock |
|
|
15
15
|
| [auth-pages.md](auth-pages.md) | The in-app auth pages: routes + guard, `VITE_MOJO_AUTH` switch, fresh-auth (440 step-up) modal, MFA panel, password tools |
|
|
16
16
|
| [admin-credentials.md](admin-credentials.md) | Group API keys and webhook subscriptions — dual-mount pages, lossless per-endpoint rate limits, permission registry, secret-safe create/reveal/rotation |
|
|
17
|
+
| [admin-presentation.md](admin-presentation.md) | KISS presentation rules, shared styles and required rendered visual QA |
|
|
17
18
|
| [admin-dashboard.md](admin-dashboard.md) | Package-owned global Admin landing, authoritative signals, independent gates, caller-isolated caches, and root fallback |
|
|
18
19
|
| [admin-cloudwatch.md](admin-cloudwatch.md) | Global EC2/RDS/Redis CloudWatch charts, exact resource/fetch wires, constrained controls, refresh ownership, and modal details |
|
|
19
20
|
| [admin-monitoring.md](admin-monitoring.md) | Monitoring Admin registration, logs, and exact Redis-backed metrics-permission mutations |
|
|
20
21
|
| [admin-metrics-explorer.md](admin-metrics-explorer.md) | Read-only recorded-metrics discovery, full-slug adapters, KPI/fan-out/scalar contracts, and cache identity |
|
|
21
22
|
| [admin-settings.md](admin-settings.md) | Runtime settings admin — direction-aware atomic writes, write-only secrets, and global/group scope |
|
|
23
|
+
| [admin-deployments.md](admin-deployments.md) | API serving/attempt evidence, WebApp release recovery, durable onboarding, transient CI keys and real uploads |
|
|
24
|
+
| [admin-dns-domains.md](admin-dns-domains.md) | Simple domain inventory, exact-name registration/adoption/purchase, focused registrar settings and DNS links |
|
|
25
|
+
| [admin-maintenance.md](admin-maintenance.md) | Independent AWS upgrade scans and framework policy, exact confirmation, observation and uncertain operation guards |
|
|
26
|
+
| [admin-geolocation.md](admin-geolocation.md) | Owner-only GeoIP provider setup, ordered fallbacks, transient credential verification and publishing |
|
|
27
|
+
| [admin-operational-fleet.md](admin-operational-fleet.md) | Operational health matrix, exact backend grants, reviewed stored capacity plans and bounded batch observation |
|
|
22
28
|
| [admin-fleet-configuration.md](admin-fleet-configuration.md) | Superuser structured configuration publishing, version restore and per-node application evidence |
|
|
23
29
|
| [admin-bouncer.md](admin-bouncer.md) | Bouncer decisions, device investigations, and bot-signature administration with token-safe caching |
|
|
24
30
|
| [admin-security-tickets.md](admin-security-tickets.md) | Ticket queue, KISS detail modal, notes, approvals, and Maestro sync contract |
|
|
@@ -36,7 +42,7 @@ everything: run the showcase (`npm run dev:showcase`) → **Develop → Componen
|
|
|
36
42
|
| [admin-dns-registrar.md](admin-dns-registrar.md) | Domain search/quote/purchase, one-use token custody, durable-ledger reconciliation, scoped registrant PII, and manual House adoption |
|
|
37
43
|
| [admin-storage.md](admin-storage.md) | Global S3 buckets, masked storage backends, explicit policy-backed File uploads, capability-safe FileView/shares, and finite rendition convergence |
|
|
38
44
|
| [admin-media-rendering.md](admin-media-rendering.md) | Storage → Media rendering: the three FILEMAN_RENDITIONS_* settings as a descriptor-driven form — delta-from-defaults writes, inline 400 routing, reset by writing `{}` |
|
|
39
|
-
| [admin-edge.md](admin-edge.md) |
|
|
45
|
+
| [admin-edge.md](admin-edge.md) | Serving hostname configuration with Address → Routing → Certificate → Review creation, independently admitted node posture and bounded hosting readiness, `site_api` routes and their create order, declared upstreams, and the fleet blocklist with log-first modes. |
|
|
40
46
|
| [admin-shortlinks.md](admin-shortlinks.md) | Global shortlink operations, destination-free caches, bounded click history, and reconciled one-shot mutations |
|
|
41
47
|
| [admin-messaging.md](admin-messaging.md) | SES domains/mailboxes/sent/templates plus public contact requests, with write-only credentials and offline HTML previews |
|
|
42
48
|
| [admin-phonehub.md](admin-phonehub.md) | Global Phone Hub: evidence-backed lookup, sanitized SMS audits, and write-only provider configuration |
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# Deployments
|
|
2
|
+
|
|
3
|
+
`DeploymentsPage` contributes one global Operations workspace. The Admin section
|
|
4
|
+
singleton belongs to `admin/domains/operations.ts`; its route lazily imports the
|
|
5
|
+
page. `WebAppDetail({id,onClose})` is a focused `modal.open` task dialog.
|
|
6
|
+
Import these through `portal-mojo/admin/operations` after central registration.
|
|
7
|
+
The domain's owned stylesheet is `styles/components/admin-deployments.css`.
|
|
8
|
+
|
|
9
|
+
API and WebApp lanes are independently admitted. API sections require exact global
|
|
10
|
+
`view_platform|manage_platform|admin`; `view_platform_security` alone never fetches
|
|
11
|
+
deployments. WebApps require exact global `view_dns|manage_dns|security` in this
|
|
12
|
+
Admin workspace. The finite Fleet `backendGlobalCan` helper reproduces backend
|
|
13
|
+
category expansion; the frontend's broader admin wildcard does not admit reads.
|
|
14
|
+
Inactive lanes and denied identities mount no domain query. No active group is
|
|
15
|
+
inherited. Explicit owning-group action scope is separate from page scope.
|
|
16
|
+
|
|
17
|
+
API uses `GET /api/account/admin/platform?sections=deployments,api`. The last
|
|
18
|
+
converged serving SHA and its observation date remain separate from the latest
|
|
19
|
+
attempt. Server node summary distinguishes restart proof, reported success,
|
|
20
|
+
dispatched and failed nodes. Durable diagnosis is separate from replaceable node
|
|
21
|
+
observations. Unknown and stale states remain visible. Recovery supports retry
|
|
22
|
+
same SHA, verify and converge according to the exact attempt status matrix; each
|
|
23
|
+
confirmation refreshes the attempt first. Retry sends a stable bounded
|
|
24
|
+
`Idempotency-Key`, then watches its returned attempt ID. There is no arbitrary SHA
|
|
25
|
+
input, API rollback, framework update or pin editor.
|
|
26
|
+
|
|
27
|
+
WebApp summary lists are bounded to 50 with honest truncation disclosure. Full
|
|
28
|
+
summary, default graph ownership, registered release history and deployment
|
|
29
|
+
attempt history are separate reads. The default graph is positively projected:
|
|
30
|
+
no bucket, prefix, key, unrelated group data or raw metadata reaches Query.
|
|
31
|
+
Full summary's latest attempt has no release identity; the detail resolves its
|
|
32
|
+
exact app/attempt-filtered generic history record before naming the version.
|
|
33
|
+
Generic attempt graphs omit the parent, so the request binds both `webapp` and
|
|
34
|
+
`id`, asks for one row, and validates the returned attempt and release IDs.
|
|
35
|
+
Ordinary viewers are never sent to the stronger rollout-status endpoint: it
|
|
36
|
+
requires WebApp SAVE authority. Admitted operators can inspect node evidence
|
|
37
|
+
through that endpoint. Selected active attempts use bounded, owner-fenced
|
|
38
|
+
observation; terminal outcomes invalidate the owning summary and history.
|
|
39
|
+
The current release pointer is desired content, never proof of fleet convergence.
|
|
40
|
+
HTTPS health and active certificates are independent observations.
|
|
41
|
+
|
|
42
|
+
Rollback requires `manage_webapp` plus the owning object's SAVE authority (`manage_dns|security`).
|
|
43
|
+
Current-user membership may be resolved only for that known app's owning group;
|
|
44
|
+
global grants bypass unnecessary membership reads. Bootstrap eligible groups do
|
|
45
|
+
not grant or narrow existing-app custom actions. Manual release registration has
|
|
46
|
+
its own exact object SAVE predicate (`manage_dns|security`); read-only `view_dns` does not grant release registration; workflow generation requires security or
|
|
47
|
+
both WebApp and DNS management. A 403 removes app mutation controls for that
|
|
48
|
+
session. The backend remains authoritative for all object, actor, origin,
|
|
49
|
+
interactive and freshness rules.
|
|
50
|
+
|
|
51
|
+
Release and deployment history have separate paged views. Eligible release rows
|
|
52
|
+
open a preselected rollback; the focused chooser also pages beyond the first 25.
|
|
53
|
+
Rollback selects a concrete noncurrent release in `uploaded|live|superseded`,
|
|
54
|
+
requires typed `app/version`, refreshes ownership/current pointer and the exact app/target-filtered release, then
|
|
55
|
+
sends `{webapp,release,group}`. It watches the exact returned deployment through
|
|
56
|
+
`/api/edge/release/deployment/ID`, validating deployment/app/release identities.
|
|
57
|
+
Only `live` is success. `rolled_back` means the attempted version was unsuccessful;
|
|
58
|
+
a failed rollout can leave mixed nodes. An uncertain rollback is not replayed on
|
|
59
|
+
remount. Its safe receipt blocks conflicting app mutations while it is unsettled.
|
|
60
|
+
|
|
61
|
+
Before creation, App and Build options share one retained draft. After creation,
|
|
62
|
+
only the current server task appears beside noninteractive App → Address →
|
|
63
|
+
Repository → HTTPS progress; operation/revision/activity live in Setup details.
|
|
64
|
+
Closing preserves setup; cancelling server setup requires explicit confirmation.
|
|
65
|
+
New WebApp uses separately admitted bootstrap eligibility and server onboarding
|
|
66
|
+
options/precheck. Missing destination or allowed bucket blocks creation with a concrete prerequisite. Existing workspaces precheck their concrete address before create. New-workspace intent deliberately has no domain before create and does not require an invented ready verdict. Defaults are production, main,
|
|
67
|
+
dist and the first allowed bucket. The durable server operation owns cursor,
|
|
68
|
+
revision, status, activity and resources. Choose/cancel use its latest observation;
|
|
69
|
+
a revision/lease refusal requires another detail read, never repeated POST.
|
|
70
|
+
Unknown cursors and parked waiting states stop automatic reads. Optional GitHub
|
|
71
|
+
verification preserves `unavailable` versus explicit attestation. Closing does not
|
|
72
|
+
cancel server work. A matching actor/origin safe receipt resumes by operation UUID;
|
|
73
|
+
an app without such a receipt shows unfinished diagnostics without creating a
|
|
74
|
+
replacement resource. An uncertain create can be deliberately retried only with
|
|
75
|
+
its immutable profile and UUID after an exact 404 observation.
|
|
76
|
+
|
|
77
|
+
Deploy opens its GitHub, Upload and Other CI methods directly. Workflow and
|
|
78
|
+
Other CI instructions use focused dialogs. Linked-key controls follow observed
|
|
79
|
+
state: create when unlinked; rotate when linked; revoke only an active key. Both
|
|
80
|
+
CI methods expose these controls. Deploy setup lazy-loads key/upload surfaces.
|
|
81
|
+
Generated YAML stays outside
|
|
82
|
+
Query and references one repository secret named `MOJO_DEPLOY_KEY`. Copy/download
|
|
83
|
+
instructions leave installation to the operator. Keys are revealed in one focused
|
|
84
|
+
transient dialog, cleared on close, authority/session replacement or unmount.
|
|
85
|
+
Receipt replay with `token:null` says the secret is unavailable and requires an
|
|
86
|
+
explicit new rotation. Rotate/revoke explain CI impact; existing content remains
|
|
87
|
+
independent. Revoke's backend freshness window is 300 seconds; other sensitive
|
|
88
|
+
custom actions use 600. A 440 prompts through `requestFreshAuth` but never replays
|
|
89
|
+
the POST; refresh and renewed explicit consent are required.
|
|
90
|
+
|
|
91
|
+
Built artifact upload is register → anonymous checksum-bound PUT → complete →
|
|
92
|
+
exact deployment observation. Files are normalized relative paths, reject
|
|
93
|
+
traversal/collisions, and are hashed with SHA-256 before registration. Defaults
|
|
94
|
+
are 5000 files and 1 GiB; backend limits may be lower. Signed destinations and File
|
|
95
|
+
objects stay transient. Each PUT uses only the returned exact checksum header,
|
|
96
|
+
raw bytes, `credentials:omit`, `redirect:error` and no API bearer. A failed/CORS
|
|
97
|
+
PUT stops completion. Resume requires reselecting and hashing an identical
|
|
98
|
+
manifest before registration remints URLs; a verified release with no uploads is
|
|
99
|
+
handled. Saved receipts contain only actor/origin, finite IDs, immutable safe
|
|
100
|
+
profile/address or normalized manifest, never key material or signed URLs.
|
|
101
|
+
|
|
102
|
+
`useDeploymentObservation` reads only known identities, stops on terminal,
|
|
103
|
+
parked/unknown cursor, failure, owner disposal or a bounded deadline, and skips
|
|
104
|
+
hidden or blurred documents. Refresh/Resume resets the read budget without
|
|
105
|
+
creating a new server operation. Native Escape/backdrop dismissal and repeated
|
|
106
|
+
submission are locked during HTTP writes. Observations can stop after close;
|
|
107
|
+
submitted server work persists and is reconciled from safe receipts.
|
|
108
|
+
|
|
109
|
+
Mock integration uses `deploymentsMock(path,opts,{user,keyBacked,authTime,group?,
|
|
110
|
+
interactive?})`, returning `undefined` for unrelated paths. The central bootstrap
|
|
111
|
+
composer consumes `readDeploymentBootstrapFacts(caller)` and merges only its
|
|
112
|
+
explicit WebApp fields. `deploymentMockStorageFetch` is an explicit mock-only
|
|
113
|
+
secondary PUT simulator; real deployments use browser fetch. Scenario controls
|
|
114
|
+
and `AdminDeploymentsDemo` exercise authority splits, current-A/failed-B,
|
|
115
|
+
reported/partial/unknown/stale evidence, same-SHA retry, rolled-back/mixed WebApps,
|
|
116
|
+
setup prerequisites, cursor/lease refusal, uncertain create, key replay, upload
|
|
117
|
+
failure and bounded observation. Fixtures establish UI contracts, not live rollout.
|
|
118
|
+
|
|
119
|
+
The supported profile editor writes only `display_name`, `environment`,
|
|
120
|
+
`github_repository`, `deployment_ref` and `build_output` through the existing
|
|
121
|
+
WebApp model save. It requires exact SAVE authority independently of
|
|
122
|
+
`manage_webapp`; owner, bucket, release pointer, slug and credential fields are
|
|
123
|
+
not editable here. The API wire field is `github_repository`, while the display
|
|
124
|
+
DTO calls it `repository`. Save re-reads ownership and all baseline values,
|
|
125
|
+
refuses observed drift, then reads back the saved profile. This is a client
|
|
126
|
+
stale-value check, not an atomic server revision condition. Profile changes do
|
|
127
|
+
not deploy content or update a workflow already installed in GitHub.
|
|
128
|
+
|
|
129
|
+
A lost profile-save response retains its submitted receipt and blocks another
|
|
130
|
+
save. Reload shows current values but does not prove the earlier writer finished.
|
|
131
|
+
Only after that read may an operator explicitly acknowledge the unknown prior
|
|
132
|
+
writer with the app-specific phrase. Acknowledgment sends no POST; a new change
|
|
133
|
+
and fresh preflight are still required. A late observed commit refuses the next
|
|
134
|
+
save. Known profile 440 refusal settles its unsent receipt and never replays the
|
|
135
|
+
POST. No profile patch or secret is retained in the receipt.
|
|
136
|
+
|
|
137
|
+
Run `node scripts/verify-admin-deployments.mjs` and
|
|
138
|
+
`node scripts/verify-admin-deployments-mounted.mjs`, then repository typecheck.
|
|
139
|
+
The first covers positive projection, authority/status/receipt/wire contracts and
|
|
140
|
+
actual client idempotency headers in both transports. Mounted StrictMode tests
|
|
141
|
+
hold responses to exercise single-flight, unsettled rollback remounts, owner
|
|
142
|
+
replacement, fresh auth without replay, one-time key replay, denied no-request
|
|
143
|
+
lanes, safe operation resume, terminal/parked/error/timeout and observer disposal.
|
|
144
|
+
The additional `verify:admin-deployments-setup-mounted` and
|
|
145
|
+
`verify:admin-webapp-inspection-mounted` commands cover state-aware setup,
|
|
146
|
+
later-page target preflight, ordinary CI viewers/observation, scoped refresh and
|
|
147
|
+
profile stale/unknown/fresh-auth journeys. The integration owner runs the
|
|
148
|
+
reviewed modal inventories and actual
|
|
149
|
+
light/dark, narrow and native-dialog browser verification.
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
New workspace continuation uses the exact `operation.group.id` returned by durable
|
|
153
|
+
create. That group identity is saved separately from the immutable create profile;
|
|
154
|
+
resuming never rewrites `group_intent:new` into another create body. The address
|
|
155
|
+
cursor reads options for that concrete group and explicitly links to the host's
|
|
156
|
+
registered Domains destination when configured and independently admitted. A new
|
|
157
|
+
workspace starts without an own/ancestor domain; configure or connect one for the
|
|
158
|
+
named group, refresh options, then precheck the address and submit the returned
|
|
159
|
+
`domain`/normalized `label` with the latest operation revision. Continue stays
|
|
160
|
+
unavailable with a concrete prerequisite until an actual address choice exists.
|
|
161
|
+
The frontend never borrows an installation-wide or unrelated workspace domain.
|
|
162
|
+
|
|
163
|
+
A WebApp deployment marked `superseded` with `terminal:true` stops observation and
|
|
164
|
+
settles its receipt, with `success:false`. It is not a successful rollout.
|
|
165
|
+
|
|
166
|
+
Upload receipts durably record `completion_submitted`, the completion timestamp,
|
|
167
|
+
and bounded prior deployment IDs before sending completion. Completion is a new
|
|
168
|
+
promotion request: after an earlier failed, rolled-back or superseded attempt,
|
|
169
|
+
repeating it can create another deployment. A lost response therefore blocks
|
|
170
|
+
implicit registration/completion even after remount or same-manifest reselection.
|
|
171
|
+
Reconcile reads the owning app summary/history and validates exact app, release,
|
|
172
|
+
version and newly observed deployment identity before observing terminal outcome.
|
|
173
|
+
Ambiguity remains unknown. Only a separately typed, freshly rechecked new deployment
|
|
174
|
+
consent permits resetting the local upload phase; that consent sends no POST and
|
|
175
|
+
requires a subsequent deliberate reselect/upload/deploy action. It neither erases
|
|
176
|
+
an earlier attempt nor silently replays it. The mock follows the backend's narrow
|
|
177
|
+
reuse rule: current release plus an active/live attempt, not permanent reuse for
|
|
178
|
+
every release ID.
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
Owner lifetimes survive React development StrictMode's setup/cleanup/setup replay.
|
|
182
|
+
Query closures keep a stable identity/scope handle whose live signal is renewed
|
|
183
|
+
before read effects resume; they do not retain an aborted first-render controller.
|
|
184
|
+
Actual unmount, actor/session replacement and authority or active-state changes
|
|
185
|
+
abort the old lifetime and discard late results. The mounted harness places
|
|
186
|
+
StrictMode above the providers/router so React 19 actually replays initial effects,
|
|
187
|
+
and verifies cold authorized bootstrap/platform reads through an asynchronous
|
|
188
|
+
transport gate as well as real owner cancellation.
|
|
189
|
+
|
|
190
|
+
### KISS presentation
|
|
191
|
+
|
|
192
|
+
API and WebApps are distinct tasks; hosts admitting only one lane show no tab
|
|
193
|
+
strip. Creation appears only in WebApps. The API lane shows last convergence and
|
|
194
|
+
attempts, keeps unavailable/stale evidence visible, and puts secondary collector
|
|
195
|
+
facts behind an info icon. API inspection separates Overview, Nodes and Activity
|
|
196
|
+
and offers recovery only on the latest applicable attempt. WebApp inspection
|
|
197
|
+
separates Overview, Deployments, Releases, Deploy and Settings; wholly read-only
|
|
198
|
+
viewers omit Deploy. Useful node evidence adds tabs to an attempt dialog only
|
|
199
|
+
when there is more than one content area. No single-item side rail or long
|
|
200
|
+
collapsible section is introduced. Admin Dashboard stays unchanged. See
|
|
201
|
+
[visual QA](admin-presentation.md).
|
|
@@ -123,8 +123,8 @@ without separate operator authorization.
|
|
|
123
123
|
|
|
124
124
|
## Shared validation setup
|
|
125
125
|
|
|
126
|
-
Use **Domains → Shared validation setup**, or **Set up shared validation** in a
|
|
127
|
-
group-managed Domain or Certificate header menu. Domain **
|
|
126
|
+
Use **Domains → Advanced → Shared validation setup**, or **Set up shared validation** in a
|
|
127
|
+
group-managed Domain or Certificate header menu. Domain **Advanced validation** and
|
|
128
128
|
Certificate **Delegation** show the same read-only facts. No new route or sidebar
|
|
129
129
|
resource is added. The flow never reads certificate material.
|
|
130
130
|
|
|
@@ -143,7 +143,7 @@ resource is added. The flow never reads certificate material.
|
|
|
143
143
|
stays available after copy/share denial or cancellation. The canonical file is
|
|
144
144
|
at most 2048 UTF-8 bytes and has exactly `version:1`, `consumer_project_uuid`,
|
|
145
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 →
|
|
146
|
+
5. The controller opens their deployment’s **Domains → Advanced → Shared validation setup →
|
|
147
147
|
Controller review**, checks access and uses **Import request**. There is no JSON
|
|
148
148
|
editor or controller URL. Empty, oversized, malformed, noncanonical or extra-field
|
|
149
149
|
files are refused before installation. Import alone grants nothing. The named
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Domains
|
|
2
|
+
|
|
3
|
+
`DomainsPage` is the everyday global DNS inventory at `/dns/domains`, under the
|
|
4
|
+
host Admin mount. Import it from `portal-mojo/admin/infrastructure`. It keeps
|
|
5
|
+
`DomainModel`, the `admin:dns:domains` table persistence key and server search,
|
|
6
|
+
provider/status filters, sorting and paging. Scope comes from each row's group
|
|
7
|
+
or Platform; the active product group is never used.
|
|
8
|
+
|
|
9
|
+
The header exposes **Register existing**, **Adopt**, and **Buy domain**. Register
|
|
10
|
+
and Buy need global `sys.manage_dns | sys.security`. Adopt also needs literal
|
|
11
|
+
`me.is_superuser === true`; the backend independently refuses noninteractive
|
|
12
|
+
and key-backed authority. Viewer sessions can inspect domains, DNS records and
|
|
13
|
+
certificates without mutation controls.
|
|
14
|
+
|
|
15
|
+
## Explicit onboarding
|
|
16
|
+
|
|
17
|
+
`showDomainOnboarding()` preserves its original menu. An optional
|
|
18
|
+
`{ initialMode: 'menu' | 'register' | 'adopt' | 'purchase' }` opens a workflow
|
|
19
|
+
directly. The page imports the dialog only after a button click.
|
|
20
|
+
|
|
21
|
+
Register existing selects one authorized group from bounded
|
|
22
|
+
`/api/dnsman/credential/group-choice`, then an active verified GoDaddy
|
|
23
|
+
credential queried through `DnsCredentialModel` with exact group/provider and
|
|
24
|
+
verification filters. No credential selector mounts before an explicit group.
|
|
25
|
+
The selector remounts by group, clears its selection on group change and rejects
|
|
26
|
+
resolved credentials from another group or unsupported/unusable credentials.
|
|
27
|
+
There is no `/api/group` read, free-form group id, provider-secret input or
|
|
28
|
+
provider-account enumeration. The exact normalized name is probed for ownership
|
|
29
|
+
without spending money. The only body is `{ group, domain, credential }`.
|
|
30
|
+
|
|
31
|
+
Adopt takes one normalized existing public zone name, then explicitly reviews
|
|
32
|
+
that name and Platform scope before posting `{ domain }`. It never supplies
|
|
33
|
+
`group` or `create_zone`, discovers inventory or assigns a tenant. Review and
|
|
34
|
+
mutation guard native dialog dismissal; Cancel review performs no mutation.
|
|
35
|
+
Registration/adoption use an immediate single-flight ref. An unknown outcome
|
|
36
|
+
invalidates inventory and requires operator review before starting another flow.
|
|
37
|
+
|
|
38
|
+
Buy preserves the bounded typed-TLD, prerequisite, tri-state search and durable
|
|
39
|
+
ledger flow documented in [the registrar reference](admin-dns-registrar.md).
|
|
40
|
+
The purchase body is exactly `{ group, purchase, confirm_token, confirm_domain,
|
|
41
|
+
confirm_price }`. Name and decimal price come from the immutable validated quote,
|
|
42
|
+
not editable confirmation inputs. The quote token is removed from its mounted
|
|
43
|
+
ref before the operation and kept transient through `withFreshAuth`; only a 440
|
|
44
|
+
may resume the identical body once. Cancelled step-up and other failures never
|
|
45
|
+
replay. An attempted purchase is terminal in that mounted wizard and reconciles
|
|
46
|
+
against the durable ledger, including ambiguous provider outcomes.
|
|
47
|
+
|
|
48
|
+
## Inspection and registrar settings
|
|
49
|
+
|
|
50
|
+
A row opens the standard `modal.detail` overview. Server-owned name, provider,
|
|
51
|
+
status, scope, registration/expiry dates and redacted failure remain read-only.
|
|
52
|
+
DNS Records is a direct shortcut for Route 53 and GoDaddy; Mojo explains its
|
|
53
|
+
certificate-only limitation. Shortcuts derive their mount from the observed DNS
|
|
54
|
+
route, so root, `/admin` and embedded prefixes work. Serving links explicitly
|
|
55
|
+
navigate to the mount's sibling `/edge/vhosts`; they are outside the registry
|
|
56
|
+
whose routes are relative to `/dns`.
|
|
57
|
+
|
|
58
|
+
Only Route 53 managers receive **Registrar settings**. Its focused guarded native
|
|
59
|
+
modal sends only changed boolean `auto_renew`/`privacy` fields to the existing
|
|
60
|
+
generic domain save endpoint. It never edits group, credentials, raw metadata,
|
|
61
|
+
protected fields or registrar contacts. Every attempted save authoritatively
|
|
62
|
+
refetches and invalidates DomainModel, including rejection. HTTP success alone
|
|
63
|
+
is not registrar success: a nonempty `last_error` stays visible with a historical
|
|
64
|
+
warning and instructions to inspect the registrar. Uncertain writes keep the
|
|
65
|
+
modal open, disable additional writes and require review. There is no automatic
|
|
66
|
+
retry. GoDaddy registrar/privacy/WHOIS management remains in GoDaddy; Mojo is
|
|
67
|
+
certificate-only. Unknown providers remain labeled and read-only.
|
|
68
|
+
|
|
69
|
+
## Advanced validation
|
|
70
|
+
|
|
71
|
+
**Domains → Advanced → Shared validation setup** opens without an existing
|
|
72
|
+
domain, preserving external-domain consumer setup and controller review.
|
|
73
|
+
Domain detail retains Advanced validation, DNS Records and Certificates sections,
|
|
74
|
+
existing registered related links and the permission/readiness-gated setup action.
|
|
75
|
+
Descriptor import/export, TLS paths and shared-validation protocol are unchanged.
|
|
76
|
+
|
|
77
|
+
## Verification and showcase
|
|
78
|
+
|
|
79
|
+
`verify-admin-domains.mjs` exercises the independent strict purchase peer,
|
|
80
|
+
fresh-auth continuation/cancellation and ambiguous no-replay. Its central mock
|
|
81
|
+
contract leg requires missing/mismatched name and decimal-price tuples to leave
|
|
82
|
+
the quote unspent. `verify-admin-domains-mounted.mjs` mounts real wizard, picker,
|
|
83
|
+
page and editor components to prove scope isolation, action authority, deliberate
|
|
84
|
+
adoption, registrar reconciliation and mount-aware navigation. The closing browser
|
|
85
|
+
pass supplies native focus, responsive layout and light/dark evidence.
|
|
86
|
+
|
|
87
|
+
The focused **Admin → Domains** showcase uses mock manager, platform and viewer
|
|
88
|
+
identities and preserves every earlier DNS showcase.
|
|
89
|
+
|
|
90
|
+
### KISS presentation
|
|
91
|
+
|
|
92
|
+
Domain/provider share one table cell. The page header owns registration/adoption/purchase; technical registrar facts are in Registration details. Provider warnings remain visible. See [visual QA](admin-presentation.md).
|
package/docs/admin-dns.md
CHANGED
|
@@ -37,6 +37,8 @@ domain includes registration/hosted-zone presence, safe zone metadata,
|
|
|
37
37
|
tracking/adoption state, and a reason. `untracked=true` returns only untracked
|
|
38
38
|
rows; discovery and assignment remain interactive-superuser operations.
|
|
39
39
|
|
|
40
|
+
The everyday inventory and three onboarding actions are documented in [admin-dns-domains.md](admin-dns-domains.md).
|
|
41
|
+
|
|
40
42
|
The operator registrar workflow is documented in [admin-dns-registrar.md](admin-dns-registrar.md). It does not use discovery: House adoption is manual exact-name only. Purchase tokens remain transient, all post-confirmation outcomes reconcile through the read-only ledger, and contact PII remains imperative/local.
|
|
41
43
|
|
|
42
44
|
These responses require local call-flow handling and must never enter Query or
|
|
@@ -87,9 +89,9 @@ rotation remains write-only and imperative. Built-in credential Delete is absent
|
|
|
87
89
|
|
|
88
90
|
## Shared wildcard validation
|
|
89
91
|
|
|
90
|
-
|
|
92
|
+
Domains offers **Advanced → Shared validation setup** to global DNS
|
|
91
93
|
managers even when server setup needs an operator. Domain detail includes
|
|
92
|
-
read-only **
|
|
94
|
+
read-only **Advanced validation**; its context action and Certificate Delegation compose
|
|
93
95
|
the same focused flow. See [the human walkthrough and exact
|
|
94
96
|
contracts](admin-dns-certificates.md#shared-validation-setup).
|
|
95
97
|
|