Skip to content

Commit b592c35

Browse files
committed
Add continuous Registry authorisation
1 parent 0027663 commit b592c35

15 files changed

Lines changed: 1051 additions & 22 deletions

‎CHANGELOG.md‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,17 @@
22

33
## Unreleased
44

5+
- Close the first-publish browser/CLI loop with `cellc publish --authorise`.
6+
cellc now creates and stores the delegated P-256 publishing key locally,
7+
opens a 15-minute exact-coordinate wallet session, and resumes publishing
8+
automatically after Registry approval; `--no-open` supports remote and
9+
terminal-only environments. Session reads expose neither the polling secret
10+
nor the resulting key ID to the browser. Submit distinguishes detected
11+
in-browser connectors from the complete external-signature directory, uses
12+
plain publishing-access language on the first-run path, states the
13+
non-replaceable release rule directly, and preserves the explicit CLI path
14+
for external wallets and CI. Artifact details now derive one recommended
15+
action from availability, verification, deployment, and consumption state.
516
- Add an isolated Pudge Testnet Registry Sandbox. Its API, Postgres database,
617
object volume, signing origin, RPC identity, website build, wallet storage,
718
and deployment evidence are separate from production. Sandbox releases are

‎docs/CELLSCRIPT_GATE_POLICY.md‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,11 @@ mainnet deployment evidence, additive migrations, worker boundary, and
6464
database/static-object shape to the CLI-generated Registry entry. It is local
6565
service coverage, not evidence
6666
that Cloudflare, R2, Hyperdrive, Neon, DNS, or a production deployment works.
67-
The CLI coverage includes the explicit first-publish admission sequence:
67+
The CLI coverage includes both first-publish admission paths: the explicit
6868
`cellc auth capability submit`, `cellc auth namespace claim`, then
69-
`cellc publish`; publisher maintenance additionally uses the capability-signed
69+
`cellc publish` sequence, and the short-lived `cellc publish --authorise`
70+
browser session in which the private publishing key remains in the local OS
71+
keychain while the CLI polls with a one-time secret. Publisher maintenance additionally uses the capability-signed
7072
`cellc artifact set-availability` path, and `cellc artifact cell-dep` performs a
7173
fresh mainnet liveness check before producing a transaction-builder descriptor.
7274
Independent reproducibility builders use `cellc auth reproducer create`; CLI

‎services/registry-api/README.md‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,10 @@ POST /v1/capabilities
131131
GET /v1/capabilities/:key_id/check?namespace=:namespace&name=:name
132132
POST /v1/capabilities/:key_id/revoke
133133
POST /v1/namespaces/claim
134+
POST /v1/authorisation-sessions
135+
GET /v1/authorisation-sessions/:session_id
136+
POST /v1/authorisation-sessions/:session_id/challenge
137+
POST /v1/authorisation-sessions/:session_id/complete
134138
135139
GET /v1/admin/audit-events
136140
GET /v1/admin/verification-queue
@@ -166,6 +170,21 @@ scope:
166170
Each form also accepts `namespace/*`. Possessing one action does not imply either
167171
of the others.
168172

173+
For an interactive first publish, `cellc publish --authorise` creates a
174+
15-minute, exact-coordinate browser session and opens the matching Registry
175+
site. The CLI generates the delegated P-256 key first and keeps its private key
176+
in the OS keychain. The API stores only the public key plus hashes of separate
177+
one-time CLI-polling and browser-approval tokens. The browser token travels in
178+
the URL fragment, not the query string, so it is absent from HTTP logs and
179+
Referer headers; browser reads never return the polling token or resulting
180+
capability key ID. After the wallet approves the
181+
server-built challenge, the Registry records the capability, claims the
182+
namespace, and the polling CLI continues the original publish automatically.
183+
Use `--no-open` to print the browser URL without launching it.
184+
185+
The explicit commands below remain the auditable/manual route for CI, external
186+
wallet signing, and recovery:
187+
169188
```bash
170189
cellc auth capability create --principal-type <principal_type> --principal-id <principal_id> \
171190
--scope publish:ns/name \

‎services/registry-api/deploy/docker-compose.production.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ services:
5353
REGISTRY_ADMIN_TOKEN: ${REGISTRY_ADMIN_TOKEN:?REGISTRY_ADMIN_TOKEN is required}
5454
REGISTRY_ORIGIN: ${REGISTRY_ORIGIN:-https://api.registry.cellscript.dev}
5555
STATIC_REGISTRY_ORIGIN: ${STATIC_REGISTRY_ORIGIN:-https://registry.cellscript.dev}
56+
REGISTRY_WEBSITE_ORIGIN: ${REGISTRY_WEBSITE_ORIGIN:-https://cellscript.dev}
5657
CKB_MAINNET_RPC_URL: ${CKB_MAINNET_RPC_URL:-https://mainnet.ckb.dev/rpc}
5758
CKB_RPC_URL: ${CKB_RPC_URL:-https://mainnet.ckb.dev/rpc}
5859
CKB_RPC_MAX_RESPONSE_BYTES: "8388608"

‎services/registry-api/deploy/docker-compose.testnet.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ services:
4343
REGISTRY_ADMIN_TOKEN: ${REGISTRY_TESTNET_ADMIN_TOKEN:?REGISTRY_TESTNET_ADMIN_TOKEN is required}
4444
REGISTRY_ORIGIN: ${REGISTRY_TESTNET_ORIGIN:-https://api.testnet.registry.cellscript.dev}
4545
STATIC_REGISTRY_ORIGIN: ${STATIC_REGISTRY_TESTNET_ORIGIN:-https://objects.testnet.registry.cellscript.dev}
46+
REGISTRY_WEBSITE_ORIGIN: ${REGISTRY_TESTNET_WEBSITE_ORIGIN:-https://testnet.registry.cellscript.dev}
4647
CKB_RPC_URL: ${CKB_TESTNET_RPC_URL:-https://testnet.ckb.dev/rpc}
4748
CKB_RPC_MAX_RESPONSE_BYTES: "8388608"
4849
CKB_MIN_CONFIRMATIONS: "4"
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
create table if not exists authorisation_sessions (
2+
session_id text primary key,
3+
poll_token_hash text not null,
4+
browser_token_hash text not null,
5+
registry_origin text not null,
6+
website_origin text not null,
7+
capability_pubkey text not null,
8+
requested_scopes text[] not null,
9+
capability_expires_at timestamptz not null,
10+
cli_version text not null,
11+
namespace text not null,
12+
name text not null,
13+
artifact_kind text not null,
14+
status text not null default 'pending',
15+
principal_type text,
16+
principal_id text,
17+
payload jsonb,
18+
challenge_token_hash text,
19+
capability_key_id text references capabilities(key_id),
20+
namespace_status text,
21+
audit_request_id text not null,
22+
created_at timestamptz not null default now(),
23+
updated_at timestamptz not null default now(),
24+
expires_at timestamptz not null,
25+
completed_at timestamptz,
26+
check (session_id ~ '^auth_[0-9a-f]{32}$'),
27+
check (poll_token_hash ~ '^sha256:[0-9a-f]{64}$'),
28+
check (browser_token_hash ~ '^sha256:[0-9a-f]{64}$'),
29+
check (cardinality(requested_scopes) > 0),
30+
check (artifact_kind in (
31+
'source_library', 'profile_library', 'runtime_verifier',
32+
'deployable_contract', 'reproducible_binary', 'template'
33+
)),
34+
check (status in ('pending', 'authorised', 'review_pending')),
35+
check (namespace_status is null or namespace_status in ('active', 'review_pending')),
36+
check (
37+
(status = 'pending' and capability_key_id is null and namespace_status is null and completed_at is null)
38+
or
39+
(status in ('authorised', 'review_pending') and capability_key_id is not null
40+
and namespace_status is not null and completed_at is not null)
41+
)
42+
);
43+
44+
create index if not exists authorisation_sessions_expiry_idx
45+
on authorisation_sessions(expires_at);

0 commit comments

Comments
 (0)