@serfab/cadre-core 1.15.0 → 1.17.0
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 +1 -1
- package/dist/bootstrap-peer-store-file.js +1 -1
- package/dist/bootstrap-peer-store.d.ts +1 -1
- package/dist/bootstrap-peer-store.js +4 -4
- package/dist/cadre-invite-protocol.d.ts +55 -138
- package/dist/cadre-invite-protocol.js +94 -449
- package/dist/cadre-invite-protocol.js.map +1 -1
- package/dist/cadre-join-request.d.ts +15 -2
- package/dist/cadre-join-request.js +22 -3
- package/dist/cadre-join-request.js.map +1 -1
- package/dist/cadre-node.d.ts +530 -247
- package/dist/cadre-node.js +1046 -525
- package/dist/cadre-node.js.map +1 -1
- package/dist/control-authorization.d.ts +36 -14
- package/dist/control-authorization.js +20 -3
- package/dist/control-authorization.js.map +1 -1
- package/dist/control-cohort.d.ts +22 -23
- package/dist/control-cohort.js +24 -24
- package/dist/control-cohort.js.map +1 -1
- package/dist/control-database.d.ts +416 -136
- package/dist/control-database.js +757 -378
- package/dist/control-database.js.map +1 -1
- package/dist/control-protocol-guard.d.ts +5 -4
- package/dist/control-protocol-guard.js +6 -3
- package/dist/control-protocol-guard.js.map +1 -1
- package/dist/control-schema-version.d.ts +80 -0
- package/dist/control-schema-version.js +203 -0
- package/dist/control-schema-version.js.map +1 -0
- package/dist/control-schema.d.ts +45 -5
- package/dist/control-schema.js +254 -70
- package/dist/control-schema.js.map +1 -1
- package/dist/control-write-retry.d.ts +5 -5
- package/dist/control-write-retry.js +10 -8
- package/dist/control-write-retry.js.map +1 -1
- package/dist/delegate-admission.d.ts +13 -0
- package/dist/delegate-admission.js +27 -0
- package/dist/delegate-admission.js.map +1 -1
- package/dist/ed25519-key.d.ts +10 -7
- package/dist/ed25519-key.js +23 -20
- package/dist/ed25519-key.js.map +1 -1
- package/dist/edge-node/config.d.ts +122 -0
- package/dist/edge-node/config.js +199 -0
- package/dist/edge-node/config.js.map +1 -0
- package/dist/edge-node/dissolve.d.ts +95 -0
- package/dist/edge-node/dissolve.js +184 -0
- package/dist/edge-node/dissolve.js.map +1 -0
- package/dist/edge-node/edge-join.d.ts +44 -0
- package/dist/edge-node/edge-join.js +227 -0
- package/dist/edge-node/edge-join.js.map +1 -0
- package/dist/edge-node/edge-node.d.ts +295 -0
- package/dist/edge-node/edge-node.js +704 -0
- package/dist/edge-node/edge-node.js.map +1 -0
- package/dist/edge-node/index.d.ts +18 -0
- package/dist/edge-node/index.js +18 -0
- package/dist/edge-node/index.js.map +1 -0
- package/dist/edge-node/join-credential.d.ts +11 -0
- package/dist/edge-node/join-credential.js +11 -0
- package/dist/edge-node/join-credential.js.map +1 -0
- package/dist/edge-node/lazy-raw-storage.d.ts +40 -0
- package/dist/edge-node/lazy-raw-storage.js +134 -0
- package/dist/edge-node/lazy-raw-storage.js.map +1 -0
- package/dist/edge-node/node-local.d.ts +60 -0
- package/dist/edge-node/node-local.js +58 -0
- package/dist/edge-node/node-local.js.map +1 -0
- package/dist/edge-node/options.d.ts +83 -0
- package/dist/edge-node/options.js +110 -0
- package/dist/edge-node/options.js.map +1 -0
- package/dist/edge-node/owner-grant.d.ts +41 -0
- package/dist/edge-node/owner-grant.js +38 -0
- package/dist/edge-node/owner-grant.js.map +1 -0
- package/dist/edge-node/platform.d.ts +140 -0
- package/dist/edge-node/platform.js +12 -0
- package/dist/edge-node/platform.js.map +1 -0
- package/dist/edge-node/strand-move.d.ts +115 -0
- package/dist/edge-node/strand-move.js +223 -0
- package/dist/edge-node/strand-move.js.map +1 -0
- package/dist/edge-node/strands.d.ts +28 -0
- package/dist/edge-node/strands.js +60 -0
- package/dist/edge-node/strands.js.map +1 -0
- package/dist/index.d.ts +16 -7
- package/dist/index.js +26 -7
- package/dist/index.js.map +1 -1
- package/dist/joined-strand-store.d.ts +3 -3
- package/dist/joined-strand-store.js +3 -3
- package/dist/joined-strand-store.js.map +1 -1
- package/dist/key-store.d.ts +9 -4
- package/dist/key-store.js +9 -4
- package/dist/key-store.js.map +1 -1
- package/dist/machine-removal.d.ts +19 -39
- package/dist/machine-removal.js +24 -98
- package/dist/machine-removal.js.map +1 -1
- package/dist/member-redemption.d.ts +250 -0
- package/dist/member-redemption.js +485 -0
- package/dist/member-redemption.js.map +1 -0
- package/dist/owner-anchor-sync.d.ts +4 -4
- package/dist/owner-anchor-sync.js +16 -15
- package/dist/owner-anchor-sync.js.map +1 -1
- package/dist/owner-grant-protocol.d.ts +247 -0
- package/dist/owner-grant-protocol.js +330 -0
- package/dist/owner-grant-protocol.js.map +1 -0
- package/dist/owner-key-export.d.ts +70 -0
- package/dist/owner-key-export.js +279 -0
- package/dist/owner-key-export.js.map +1 -0
- package/dist/owner-key-flows.d.ts +55 -0
- package/dist/owner-key-flows.js +60 -0
- package/dist/owner-key-flows.js.map +1 -0
- package/dist/owner-key-store.d.ts +31 -0
- package/dist/owner-key-store.js +81 -0
- package/dist/owner-key-store.js.map +1 -0
- package/dist/owner-keys.d.ts +78 -0
- package/dist/owner-keys.js +133 -0
- package/dist/owner-keys.js.map +1 -0
- package/dist/owner-signer.d.ts +54 -0
- package/dist/owner-signer.js +51 -0
- package/dist/owner-signer.js.map +1 -0
- package/dist/peer-authorization.d.ts +83 -18
- package/dist/peer-authorization.js +123 -53
- package/dist/peer-authorization.js.map +1 -1
- package/dist/provider/rent-node.js +1 -1
- package/dist/provider/rent-node.js.map +1 -1
- package/dist/seed-bootstrap.d.ts +131 -109
- package/dist/seed-bootstrap.js +260 -248
- package/dist/seed-bootstrap.js.map +1 -1
- package/dist/seed-trust-policy.js +4 -4
- package/dist/strand-addr-protocol.d.ts +4 -1
- package/dist/strand-addr-protocol.js +8 -2
- package/dist/strand-addr-protocol.js.map +1 -1
- package/dist/strand-cohort.d.ts +3 -0
- package/dist/strand-cohort.js.map +1 -1
- package/dist/strand-database.d.ts +1 -0
- package/dist/strand-database.js +3 -0
- package/dist/strand-database.js.map +1 -1
- package/dist/strand-first-sync-gate.d.ts +4 -3
- package/dist/strand-first-sync-gate.js +4 -3
- package/dist/strand-first-sync-gate.js.map +1 -1
- package/dist/strand-instance-manager.d.ts +1 -1
- package/dist/strand-membership-writer.d.ts +13 -2
- package/dist/strand-membership-writer.js +52 -16
- package/dist/strand-membership-writer.js.map +1 -1
- package/dist/strand-move.d.ts +6 -5
- package/dist/strand-move.js +31 -30
- package/dist/strand-move.js.map +1 -1
- package/dist/strand-peer-redial.js +2 -3
- package/dist/strand-peer-redial.js.map +1 -1
- package/dist/types.d.ts +286 -103
- package/dist/types.js.map +1 -1
- package/package.json +16 -7
- package/src/bootstrap-peer-store-file.ts +44 -44
- package/src/bootstrap-peer-store.ts +214 -214
- package/src/cadre-invite-protocol.ts +131 -531
- package/src/cadre-join-request.ts +188 -167
- package/src/cadre-node.ts +1166 -541
- package/src/control-authorization.ts +47 -14
- package/src/control-cohort.ts +127 -128
- package/src/control-database.ts +940 -456
- package/src/control-protocol-guard.ts +7 -4
- package/src/control-schema-version.ts +251 -0
- package/src/control-schema.ts +265 -70
- package/src/control-write-retry.ts +569 -567
- package/src/delegate-admission.ts +37 -0
- package/src/ed25519-key.ts +174 -171
- package/src/edge-node/config.ts +277 -0
- package/src/edge-node/dissolve.ts +251 -0
- package/src/edge-node/edge-join.ts +319 -0
- package/src/edge-node/edge-node.ts +1045 -0
- package/src/edge-node/index.ts +59 -0
- package/src/edge-node/join-credential.ts +16 -0
- package/src/edge-node/lazy-raw-storage.ts +178 -0
- package/src/edge-node/node-local.ts +84 -0
- package/src/edge-node/options.ts +179 -0
- package/src/edge-node/owner-grant.ts +63 -0
- package/src/edge-node/platform.ts +151 -0
- package/src/edge-node/strand-move.ts +270 -0
- package/src/edge-node/strands.ts +72 -0
- package/src/index.ts +102 -5
- package/src/joined-strand-store.ts +4 -4
- package/src/key-store.ts +10 -4
- package/src/machine-removal.ts +26 -111
- package/src/member-redemption.ts +642 -0
- package/src/owner-anchor-sync.ts +19 -18
- package/src/owner-grant-protocol.ts +532 -0
- package/src/owner-key-export.ts +348 -0
- package/src/owner-key-flows.ts +109 -0
- package/src/owner-key-store.ts +85 -0
- package/src/owner-keys.ts +178 -0
- package/src/owner-signer.ts +94 -0
- package/src/peer-authorization.ts +558 -488
- package/src/provider/rent-node.ts +1 -1
- package/src/seed-bootstrap.ts +301 -312
- package/src/seed-trust-policy.ts +4 -4
- package/src/strand-addr-protocol.ts +547 -538
- package/src/strand-cohort.ts +4 -0
- package/src/strand-database.ts +3 -0
- package/src/strand-first-sync-gate.ts +4 -3
- package/src/strand-instance-manager.ts +1 -1
- package/src/strand-membership-writer.ts +61 -16
- package/src/strand-move.ts +45 -36
- package/src/strand-peer-redial.ts +2 -3
- package/src/types.ts +304 -103
package/dist/control-schema.js
CHANGED
|
@@ -1,15 +1,39 @@
|
|
|
1
|
+
import { Parser } from '@quereus/quereus';
|
|
1
2
|
/**
|
|
2
|
-
*
|
|
3
|
+
* The version of the declared control schema, carried in the schema text as the
|
|
4
|
+
* {@link CONTROL_SCHEMA_VERSION_TAG} tag on the `OwnerKey` table. A warm start compares
|
|
5
|
+
* it with the version the store records before applying anything
|
|
6
|
+
* (`control-schema-version.ts`, which also says why that is the version the store was
|
|
7
|
+
* created under).
|
|
3
8
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
9
|
+
* When it changes, what a new version may change, and the fixture each version keeps:
|
|
10
|
+
* docs/architecture.md → "Control schema changes and incompatible stores", enforced by
|
|
11
|
+
* `control-schema-versions.spec.ts`.
|
|
12
|
+
*/
|
|
13
|
+
export const CONTROL_SCHEMA_VERSION = 3;
|
|
14
|
+
/**
|
|
15
|
+
* The first control schema version whose fixture is kept, and the oldest a store can be
|
|
16
|
+
* migrated from. Stores that record no version (written by 1.16.0 and earlier) are not
|
|
17
|
+
* migrated; docs/architecture.md says why.
|
|
18
|
+
*/
|
|
19
|
+
export const CONTROL_SCHEMA_BASELINE_VERSION = 3;
|
|
20
|
+
/** The `OwnerKey` table tag that records {@link CONTROL_SCHEMA_VERSION} in the schema and in every store. */
|
|
21
|
+
export const CONTROL_SCHEMA_VERSION_TAG = 'sereus.controlSchemaVersion';
|
|
22
|
+
/**
|
|
23
|
+
* The `declare schema CadreControl { … }` statement, with its header comment.
|
|
24
|
+
*
|
|
25
|
+
* Together with {@link APPLY_CONTROL_SCHEMA} this is the authoritative runtime copy of
|
|
26
|
+
* the CadreControl authorization schema ({@link CONTROL_SCHEMA}). It is duplicated from
|
|
27
|
+
* `schemas/control.qsql` so that React Native and other filesystem-less environments
|
|
28
|
+
* get the schema without a runtime file read. Held apart from the apply because
|
|
29
|
+
* `ControlDatabase.loadSchema` declares, checks the pending changes, and only then
|
|
30
|
+
* applies.
|
|
7
31
|
*
|
|
8
32
|
* The two copies MUST stay identical — `control-schema-drift.spec.ts` fails the
|
|
9
33
|
* build if they drift. Any edit here must be mirrored in `schemas/control.qsql`
|
|
10
34
|
* and vice versa.
|
|
11
35
|
*/
|
|
12
|
-
export const
|
|
36
|
+
export const CONTROL_SCHEMA_DECLARATION = `-- A Sereus party's cadre (its nodes) and their participation in strands (networks).
|
|
13
37
|
--
|
|
14
38
|
-- Every write is authorized by a check: an owner signs an action-tagged digest of the row
|
|
15
39
|
-- (cadre-core control-authorization.ts), or a peer signs its own record. Each digest leads
|
|
@@ -21,13 +45,14 @@ export const CONTROL_SCHEMA = `-- A Sereus party's cadre (its nodes) and their p
|
|
|
21
45
|
-- two digests scoped by the invitation token instead (FormationUsage.Authorized).
|
|
22
46
|
--
|
|
23
47
|
-- Rows of the guarded tables (OwnerKey, ValidationKey, Strand, StrandPartyKey, JoinedStrand,
|
|
24
|
-
-- JoinRequest, CadrePeer, DeviceToken, CadreInvite) carry a one-off StampId bound
|
|
25
|
-
-- add and remove digests. \`unique\` holds over live rows only, so a delete retires
|
|
26
|
-
-- into Revocation in the same transaction (RevocationRecorded) and an insert refuses
|
|
27
|
-
-- stamp (NotRevoked): the never-expiring add approval cannot re-seat a removed row.
|
|
28
|
-
-- legitimate re-add mints a fresh stamp and a fresh signature. CadreInvite
|
|
29
|
-
--
|
|
30
|
-
-- because the rows it admitted prove
|
|
48
|
+
-- JoinRequest, CadrePeer, DeviceToken, CadreInvite, OwnerGrant) carry a one-off StampId bound
|
|
49
|
+
-- into their add and remove digests. \`unique\` holds over live rows only, so a delete retires
|
|
50
|
+
-- the stamp into Revocation in the same transaction (RevocationRecorded) and an insert refuses
|
|
51
|
+
-- a retired stamp (NotRevoked): the never-expiring add approval cannot re-seat a removed row.
|
|
52
|
+
-- A legitimate re-add mints a fresh stamp and a fresh signature. CadreInvite and OwnerGrant
|
|
53
|
+
-- are the two guarded tables that are never deleted: a tombstone there withdraws the
|
|
54
|
+
-- invitation or grant while the row stays, because the rows it admitted prove themselves
|
|
55
|
+
-- through it.
|
|
31
56
|
--
|
|
32
57
|
-- A check whose expression evaluates to null passes (SQL three-valued logic), so every
|
|
33
58
|
-- comparison over a nullable column that is meant to pin a value is written null-safe
|
|
@@ -47,12 +72,16 @@ export const CONTROL_SCHEMA = `-- A Sereus party's cadre (its nodes) and their p
|
|
|
47
72
|
declare schema CadreControl {
|
|
48
73
|
-- A key that can authorize control changes. A row is seated one of three ways, told apart
|
|
49
74
|
-- by the vouch columns: the founding row (all three null), an owner-signed add (VouchOwner
|
|
50
|
-
-- and VouchSig pinned to the insert context, VouchUsage null), or an owner
|
|
51
|
-
--
|
|
52
|
-
--
|
|
53
|
-
--
|
|
75
|
+
-- and VouchSig pinned to the insert context, VouchUsage null), or an owner grant redeemed
|
|
76
|
+
-- by consent (VouchOwner = the grant's IssuerKey, VouchSig null, VouchUsage = the
|
|
77
|
+
-- OwnerGrantUsage row that seated it). A machine invitation (CadreInvite) admits a machine
|
|
78
|
+
-- and never seats a row here: a machine's identity key is never an owner key. A reader
|
|
79
|
+
-- judges the stored proof against its node-local anchor, never against this replicated
|
|
80
|
+
-- table.
|
|
54
81
|
table OwnerKey (
|
|
55
82
|
Key text primary key,
|
|
83
|
+
Label text null, -- the user's name for the key ("phone", "paper backup"); bound into the
|
|
84
|
+
-- signed add, so a relayed approval cannot seat the key under another name
|
|
56
85
|
StampId text unique,
|
|
57
86
|
VouchOwner text null,
|
|
58
87
|
VouchSig text null,
|
|
@@ -60,6 +89,10 @@ declare schema CadreControl {
|
|
|
60
89
|
constraint NotRevoked check on insert (
|
|
61
90
|
not exists (select 1 from Revocation R where R.TableName = 'OwnerKey' and R.StampId = new.StampId)
|
|
62
91
|
),
|
|
92
|
+
-- Never empty: the add digest binds coalesce(Label, ''), so an empty label would sign as none.
|
|
93
|
+
constraint LabelLength check (
|
|
94
|
+
Label is null or length(Label) between 1 and 64
|
|
95
|
+
),
|
|
63
96
|
-- The tombstone must name the removed row, not just its stamp (Revocation.RowKey).
|
|
64
97
|
constraint RevocationRecorded check on delete (
|
|
65
98
|
exists (select 1 from Revocation R where R.TableName = 'OwnerKey' and R.StampId = old.StampId and R.RowKey = old.Key)
|
|
@@ -81,29 +114,34 @@ declare schema CadreControl {
|
|
|
81
114
|
-- deliberately raw, the one owner read here that ignores Revocation: a machine holding only
|
|
82
115
|
-- a retired owner row must still be refused a second genesis, or a removed device could
|
|
83
116
|
-- re-found the party on its own copy. An owner cannot sign its own removal.
|
|
84
|
-
-- The consent branch seats an owner with no signature at all:
|
|
85
|
-
-- written in the same transaction names this exact row (Key and stamp), and the
|
|
86
|
-
--
|
|
87
|
-
--
|
|
88
|
-
-- redeemed in one transaction; the usage
|
|
117
|
+
-- The consent branch seats an owner with no signature at all: an OwnerGrantUsage row
|
|
118
|
+
-- written in the same transaction names this exact row (Key and stamp), and the grant
|
|
119
|
+
-- it redeemed was issued by the stored VouchOwner and carries the row's label (the
|
|
120
|
+
-- issuer's choice, bound into the grant's signature). The grant is read from its
|
|
121
|
+
-- committed table, so it cannot be seated and redeemed in one transaction; the usage
|
|
122
|
+
-- row carries the liveness conditions.
|
|
89
123
|
constraint Authorized check on insert, delete (
|
|
90
124
|
(old.Key is null and (select count(1) from committed.OwnerKey) = 0
|
|
91
125
|
and new.VouchOwner is null and new.VouchSig is null and new.VouchUsage is null)
|
|
92
|
-
or (old.Key is null and exists (select 1 from committed.OwnerKey A where A.Key = context.OwnerKey and not exists (select 1 from Revocation R where R.TableName = 'OwnerKey' and R.StampId = A.StampId) and verify(digest('CadreControl.OwnerKey', 'add', party_id(), new.Key, new.StampId), context.Signature, A.Key, 'ed25519'))
|
|
126
|
+
or (old.Key is null and exists (select 1 from committed.OwnerKey A where A.Key = context.OwnerKey and not exists (select 1 from Revocation R where R.TableName = 'OwnerKey' and R.StampId = A.StampId) and verify(digest('CadreControl.OwnerKey', 'add', party_id(), new.Key, coalesce(new.Label, ''), new.StampId), context.Signature, A.Key, 'ed25519'))
|
|
93
127
|
and coalesce(new.VouchOwner, '') = context.OwnerKey
|
|
94
128
|
and coalesce(new.VouchSig, '') = context.Signature
|
|
95
129
|
and new.VouchUsage is null)
|
|
96
130
|
or (old.Key is null and new.VouchSig is null and new.VouchUsage is not null
|
|
97
131
|
and exists (
|
|
98
|
-
select 1 from
|
|
132
|
+
select 1 from OwnerGrantUsage U
|
|
99
133
|
where U.UsageStampId = new.VouchUsage
|
|
100
|
-
and U.
|
|
101
|
-
and U.
|
|
102
|
-
and exists (select 1 from committed.
|
|
134
|
+
and U.SeatedKey = new.Key
|
|
135
|
+
and U.SeatedStampId = new.StampId
|
|
136
|
+
and exists (select 1 from committed.OwnerGrant G
|
|
137
|
+
where G.Key = U.GrantKey and G.IssuerKey = new.VouchOwner
|
|
138
|
+
and coalesce(G.Label, '') = coalesce(new.Label, ''))
|
|
103
139
|
))
|
|
104
140
|
or (new.Key is null and exists (select 1 from committed.OwnerKey A where A.Key = context.OwnerKey and A.Key <> old.Key and not exists (select 1 from Revocation R where R.TableName = 'OwnerKey' and R.StampId = A.StampId) and verify(digest('CadreControl.OwnerKey', 'remove', party_id(), old.Key, old.StampId), context.Signature, A.Key, 'ed25519')))
|
|
105
141
|
)
|
|
106
|
-
|
|
142
|
+
-- The tag is the version of this whole schema (cadre-core CONTROL_SCHEMA_VERSION): every edit
|
|
143
|
+
-- to the schema bumps it, and a warm start reads the store's copy before applying anything.
|
|
144
|
+
) with tags ("${CONTROL_SCHEMA_VERSION_TAG}" = ${CONTROL_SCHEMA_VERSION}) with context (OwnerKey text null, Signature text null);
|
|
107
145
|
|
|
108
146
|
-- A key that can validate a strand formation disclosure (FormationUsage.Authorized).
|
|
109
147
|
table ValidationKey (
|
|
@@ -136,9 +174,12 @@ declare schema CadreControl {
|
|
|
136
174
|
Id text primary key, -- UUID
|
|
137
175
|
MemberPrivateKey text null unique, -- the strand's shared read secret; closed strands only
|
|
138
176
|
Type text, -- 'o' open | 'c' closed: open gates writes in the sApp, only closed gates reads
|
|
139
|
-
FounderOwnerKey text null, -- owner key
|
|
140
|
-
--
|
|
141
|
-
|
|
177
|
+
FounderOwnerKey text null, -- the owner key that signed the insert; null on a consent-seated strand,
|
|
178
|
+
-- whose insert carries no signature. Provenance, not content (strandRowMismatches).
|
|
179
|
+
FounderPeerId text null, -- peer id of the machine that runs the founder bootstrap (cadre-node.ts
|
|
180
|
+
-- launchStrand), bound into the signed add; null on a consent-seated strand.
|
|
181
|
+
-- Not pinned to a CadrePeer row: a solo founder publishes before its own
|
|
182
|
+
-- row exists, and only an owner can name it. Provenance, as FounderOwnerKey.
|
|
142
183
|
StampId text unique,
|
|
143
184
|
constraint NotRevoked check on insert (
|
|
144
185
|
not exists (select 1 from Revocation R where R.TableName = 'Strand' and R.StampId = new.StampId)
|
|
@@ -149,9 +190,10 @@ declare schema CadreControl {
|
|
|
149
190
|
-- The consent branch below carries no signature, so an update rule would let anyone rewrite
|
|
150
191
|
-- a consent-seated strand.
|
|
151
192
|
constraint NoUpdate check on update (false),
|
|
152
|
-
-- Owner-signed, with FounderOwnerKey pinned to the verified signer
|
|
153
|
-
-- FormationUsage row naming this exact row (id
|
|
154
|
-
-- (ControlDatabase.redeemInvitation). Binding
|
|
193
|
+
-- Owner-signed, with FounderOwnerKey pinned to the verified signer and FounderPeerId bound
|
|
194
|
+
-- into the signature; or consent-seated by a FormationUsage row naming this exact row (id
|
|
195
|
+
-- and stamp), written in the same transaction (ControlDatabase.redeemInvitation). Binding
|
|
196
|
+
-- the stamp is what makes a removal stick:
|
|
155
197
|
-- the usage row outlives the strand, and keyed on the id alone it would re-authorize an
|
|
156
198
|
-- unsigned re-seat under a fresh stamp. The consent branch is narrow, each clause closing
|
|
157
199
|
-- one door:
|
|
@@ -164,12 +206,14 @@ declare schema CadreControl {
|
|
|
164
206
|
-- A standalone tombstone (no accompanying delete, Revocation.Authorized) lets an owner
|
|
165
207
|
-- foreclose consent-seating of an id that never existed: owner-only, and ids are random.
|
|
166
208
|
constraint AuthorizedInsert check on insert (
|
|
167
|
-
(exists (select 1 from OwnerKey A where A.Key = context.OwnerKey and not exists (select 1 from Revocation R where R.TableName = 'OwnerKey' and R.StampId = A.StampId) and verify(digest('CadreControl.Strand', 'add', party_id(), new.Id, new.Type, coalesce(new.MemberPrivateKey, ''), new.StampId), context.Signature, A.Key, 'ed25519'))
|
|
168
|
-
and new.FounderOwnerKey = context.OwnerKey
|
|
209
|
+
(exists (select 1 from OwnerKey A where A.Key = context.OwnerKey and not exists (select 1 from Revocation R where R.TableName = 'OwnerKey' and R.StampId = A.StampId) and verify(digest('CadreControl.Strand', 'add', party_id(), new.Id, new.Type, coalesce(new.MemberPrivateKey, ''), new.FounderPeerId, new.StampId), context.Signature, A.Key, 'ed25519'))
|
|
210
|
+
and new.FounderOwnerKey = context.OwnerKey
|
|
211
|
+
and new.FounderPeerId is not null)
|
|
169
212
|
or (
|
|
170
213
|
new.Type = 'o'
|
|
171
214
|
and new.MemberPrivateKey is null
|
|
172
215
|
and new.FounderOwnerKey is null
|
|
216
|
+
and new.FounderPeerId is null
|
|
173
217
|
and exists (
|
|
174
218
|
select 1 from FormationUsage FU
|
|
175
219
|
where FU.StrandId = new.Id
|
|
@@ -623,11 +667,13 @@ declare schema CadreControl {
|
|
|
623
667
|
-- convergence is guarded by the integration scenario strand-formation-concurrent-redemption.
|
|
624
668
|
index FormationUsageByToken on FormationUsage (Token);
|
|
625
669
|
|
|
626
|
-
-- An owner-signed invitation to join this cadre, redeemable on the owner's
|
|
627
|
-
-- member machine (ControlDatabase.redeemCadreInvite).
|
|
670
|
+
-- An owner-signed invitation to join this cadre as a machine, redeemable on the owner's
|
|
671
|
+
-- behalf by any member machine (ControlDatabase.redeemCadreInvite). It admits a machine
|
|
672
|
+
-- and grants nothing else; ownership is an OwnerGrant. The invitation is a keypair, not a
|
|
628
673
|
-- bearer token: the row holds the public half and the holder proves possession by signing
|
|
629
|
-
-- with the private half (CadreInviteUsage.InvitePossessed), so
|
|
630
|
-
-- can
|
|
674
|
+
-- with the private half (CadreInviteUsage.InvitePossessed), so a member that only relays
|
|
675
|
+
-- it can neither admit a machine of its own choosing with it nor spend its uses. Rows are
|
|
676
|
+
-- never deleted: a device admitted
|
|
631
677
|
-- through one carries no owner signature of its own, and its membership is the chain
|
|
632
678
|
-- invitation -> usage -> peer row, verified at read time, so the row must outlive every
|
|
633
679
|
-- device it admitted. Withdrawing an invitation is an owner-signed Revocation tombstone
|
|
@@ -640,7 +686,6 @@ declare schema CadreControl {
|
|
|
640
686
|
table CadreInvite (
|
|
641
687
|
Key text primary key, -- the invitation's ed25519 public key (base64url)
|
|
642
688
|
PeerId text null, -- the device this invitation is for; null: whoever redeems first designates it
|
|
643
|
-
GrantsOwner integer check (GrantsOwner = 0 or GrantsOwner = 1), -- 1: redemption also seats an OwnerKey row
|
|
644
689
|
ExpiresAt datetime null,
|
|
645
690
|
TotalUses int null check (TotalUses >= 0),
|
|
646
691
|
IssuerKey text, -- the owner that signed the row (== insert context.OwnerKey). A reader checks it
|
|
@@ -661,7 +706,6 @@ declare schema CadreControl {
|
|
|
661
706
|
'CadreControl.CadreInvite', 'add', party_id(),
|
|
662
707
|
new.Key,
|
|
663
708
|
coalesce(new.PeerId, ''),
|
|
664
|
-
cast(new.GrantsOwner as text),
|
|
665
709
|
coalesce(cast(new.ExpiresAt as text), ''),
|
|
666
710
|
coalesce(cast(new.TotalUses as text), ''),
|
|
667
711
|
new.StampId
|
|
@@ -676,8 +720,7 @@ declare schema CadreControl {
|
|
|
676
720
|
) with context (OwnerKey text, Signature text);
|
|
677
721
|
|
|
678
722
|
-- Append-only record of cadre invitation redemptions, one row per redemption: the proof a
|
|
679
|
-
-- CadrePeer row
|
|
680
|
-
-- consent rather than by an owner signature.
|
|
723
|
+
-- CadrePeer row was admitted by consent rather than by an owner signature.
|
|
681
724
|
table CadreInviteUsage (
|
|
682
725
|
UsageStampId text primary key, -- nonce minted by the redeeming device and signed into both signatures
|
|
683
726
|
-- below. The primary key: this table never deletes, so the key alone
|
|
@@ -691,22 +734,20 @@ declare schema CadreControl {
|
|
|
691
734
|
PeerStampId text, -- the CadrePeer.StampId this usage seats: one row incarnation, not a peer id
|
|
692
735
|
-- forever. Minted by the writer inside the redeeming transaction and not
|
|
693
736
|
-- signed (FormationUsage.StrandStampId).
|
|
694
|
-
OwnerStampId text null, -- the OwnerKey.StampId this usage seats when the invitation grants ownership
|
|
695
737
|
InviteSig text, -- by the invitation's private key over the 'redeem' digest: proof of possession
|
|
696
738
|
PeerSig text, -- by PeerKey over the 'consent' digest: the device agreed to join
|
|
697
739
|
constraint InsertOnly check on update, delete (false),
|
|
698
740
|
-- The invitation is read from the pre-transaction snapshot, so an invitation cannot be
|
|
699
|
-
-- seated and redeemed in one transaction (the
|
|
741
|
+
-- seated and redeemed in one transaction (the CadrePeer consent branch rests on that).
|
|
700
742
|
-- NOTE: accepted tradeoff — the use cap counts committed usage, so two redeemers racing
|
|
701
|
-
-- for a single-use invitation on different machines may both be admitted until
|
|
702
|
-
-- and after merge both rows stand (FormationUsage.Authorized)
|
|
703
|
-
--
|
|
704
|
-
-- the
|
|
705
|
-
--
|
|
706
|
-
--
|
|
707
|
-
--
|
|
708
|
-
--
|
|
709
|
-
-- satisfies); devices it already admitted stay members.
|
|
743
|
+
-- for a single-use machine invitation on different machines may both be admitted until
|
|
744
|
+
-- merge, and after merge both rows stand (FormationUsage.Authorized). Serializing would
|
|
745
|
+
-- need cross-machine coordination the control plane does not have; the mitigations are
|
|
746
|
+
-- the single-use default, the targeted form, and the owner seeing the extra machine and
|
|
747
|
+
-- removing it. Revisit if the control plane gains a cross-machine sequencer. The owner
|
|
748
|
+
-- grant's half of this tradeoff is at OwnerGrantUsage.Authorized. An issuer removed
|
|
749
|
+
-- since issuing takes its outstanding invitations with it (the committed.OwnerKey
|
|
750
|
+
-- clause, which a tombstone alone satisfies); devices it already admitted stay members.
|
|
710
751
|
constraint Authorized check on insert (
|
|
711
752
|
exists (
|
|
712
753
|
select 1 from committed.CadreInvite I
|
|
@@ -731,33 +772,143 @@ declare schema CadreControl {
|
|
|
731
772
|
),
|
|
732
773
|
-- Deferred, so the same-transaction peer insert counts: a usage row can never be held in
|
|
733
774
|
-- reserve to seat a row later (FormationUsage.StrandExists). PeerKey must be the key the
|
|
734
|
-
-- peer row stores
|
|
735
|
-
-- OwnerKey row (no peer insert to pin it) cannot name a key other than that device's.
|
|
775
|
+
-- peer row stores, so the usage names the admitted machine's own key and no other.
|
|
736
776
|
constraint PeerExists check (exists (
|
|
737
777
|
select 1 from CadrePeer P where P.PeerId = new.PeerId and P.StampId = new.PeerStampId and P.PublicKey = new.PeerKey
|
|
738
|
-
))
|
|
739
|
-
constraint OwnerExists check (
|
|
740
|
-
new.OwnerStampId is null
|
|
741
|
-
or exists (select 1 from OwnerKey K where K.Key = new.PeerKey and K.StampId = new.OwnerStampId)
|
|
742
|
-
)
|
|
778
|
+
))
|
|
743
779
|
) with context (Now datetime);
|
|
744
780
|
|
|
745
781
|
-- Serves the cap count above and the liveness reads (cadre-core countCadreInviteUsage,
|
|
746
782
|
-- hasLiveCadreInvite) on an append-only table, as FormationUsageByToken does.
|
|
747
783
|
index CadreInviteUsageByInvite on CadreInviteUsage (InviteKey);
|
|
748
784
|
|
|
785
|
+
-- An owner-signed grant of ownership to whoever holds the grant's private half: it seats an
|
|
786
|
+
-- OwnerKey row for a key the holder generates or already holds, and admits no machine (a
|
|
787
|
+
-- machine is admitted by a CadreInvite; peer identity and ownership are unrelated, so the
|
|
788
|
+
-- row names no peer id). The grant is a keypair as the invitation is: the row holds the
|
|
789
|
+
-- public half, the holder proves possession by signing with the private half
|
|
790
|
+
-- (OwnerGrantUsage.GrantPossessed), and the member machine that writes the redemption can
|
|
791
|
+
-- verify that signature but never produce it, so it cannot seat an owner for itself. Rows
|
|
792
|
+
-- are never deleted: a key seated through one carries no owner signature of its own, and
|
|
793
|
+
-- its proof is the chain grant -> usage -> OwnerKey row, verified at read time, so the row
|
|
794
|
+
-- must outlive every key it seated. Withdrawal is an owner-signed Revocation tombstone over
|
|
795
|
+
-- the row's stamp with the row kept (Revocation.RowIsGone); liveness is read as no
|
|
796
|
+
-- tombstone, unexpired, uses left, issuer still an owner (OwnerGrantUsage.Authorized).
|
|
797
|
+
-- NOTE: expired and withdrawn rows accumulate for the life of the party, as CadreInvite's.
|
|
798
|
+
-- The label is the issuer's: it is bound into the grant's signature and the seated OwnerKey
|
|
799
|
+
-- row must carry it (the grant branch of OwnerKey.Authorized), so a key seated on a fresh
|
|
800
|
+
-- device during recovery needs no naming prompt, and nothing the holder writes names it.
|
|
801
|
+
table OwnerGrant (
|
|
802
|
+
Key text primary key, -- the grant's ed25519 public key (base64url)
|
|
803
|
+
Label text null, -- the label the seated OwnerKey row carries, chosen by the issuer
|
|
804
|
+
ExpiresAt datetime null, -- null: never. The writer defaults to a short expiry; a lifetime with
|
|
805
|
+
-- no end is the issuer's explicit choice (a backup grant)
|
|
806
|
+
TotalUses int null check (TotalUses >= 0),
|
|
807
|
+
IssuerKey text, -- the owner that signed the row (== insert context.OwnerKey); a reader checks
|
|
808
|
+
-- it against its node-local anchor, never against the replicated OwnerKey table
|
|
809
|
+
IssuerSig text, -- that owner's 'add' signature (== insert context.Signature), stored so any
|
|
810
|
+
-- reader can re-verify the row from the holder's copy or the replicated one
|
|
811
|
+
StampId text unique,
|
|
812
|
+
-- A withdrawn grant cannot be re-seated from the signed copy its holder keeps, on any
|
|
813
|
+
-- node that holds the tombstone (schema header for the node that does not).
|
|
814
|
+
constraint NotRevoked check on insert (
|
|
815
|
+
not exists (select 1 from Revocation R where R.TableName = 'OwnerGrant' and R.StampId = new.StampId)
|
|
816
|
+
),
|
|
817
|
+
-- Never empty, as OwnerKey.LabelLength: the add digest binds coalesce(Label, '').
|
|
818
|
+
constraint LabelLength check (
|
|
819
|
+
Label is null or length(Label) between 1 and 64
|
|
820
|
+
),
|
|
821
|
+
-- The owner signs the whole row, nullable columns as '' (cadre-core ownerGrantRowFields),
|
|
822
|
+
-- and the stored issuer pair must be the pair verified here, as CadreInvite pins its issuer.
|
|
823
|
+
constraint AuthorizedInsert check on insert (
|
|
824
|
+
exists (select 1 from OwnerKey A where A.Key = context.OwnerKey and not exists (select 1 from Revocation R where R.TableName = 'OwnerKey' and R.StampId = A.StampId) and verify(
|
|
825
|
+
digest(
|
|
826
|
+
'CadreControl.OwnerGrant', 'add', party_id(),
|
|
827
|
+
new.Key,
|
|
828
|
+
coalesce(new.Label, ''),
|
|
829
|
+
coalesce(cast(new.ExpiresAt as text), ''),
|
|
830
|
+
coalesce(cast(new.TotalUses as text), ''),
|
|
831
|
+
new.StampId
|
|
832
|
+
),
|
|
833
|
+
context.Signature, A.Key, 'ed25519'))
|
|
834
|
+
and coalesce(new.IssuerKey, '') = context.OwnerKey
|
|
835
|
+
and coalesce(new.IssuerSig, '') = context.Signature
|
|
836
|
+
),
|
|
837
|
+
constraint NoUpdate check on update (false),
|
|
838
|
+
-- Never deleted (table comment). Withdrawal is the tombstone alone.
|
|
839
|
+
constraint NoDelete check on delete (false)
|
|
840
|
+
) with context (OwnerKey text, Signature text);
|
|
841
|
+
|
|
842
|
+
-- Append-only record of owner-grant redemptions, one row per redemption: the proof an
|
|
843
|
+
-- OwnerKey row was seated by consent rather than by an owner signature.
|
|
844
|
+
table OwnerGrantUsage (
|
|
845
|
+
UsageStampId text primary key, -- nonce minted by the holder and signed into both signatures below. The
|
|
846
|
+
-- primary key: this table never deletes, so the key alone makes a nonce
|
|
847
|
+
-- permanent and there is no NotRevoked pair here (CadreInviteUsage).
|
|
848
|
+
GrantKey text, -- the OwnerGrant redeemed
|
|
849
|
+
SeatedKey text, -- the owner key seated (base64url ed25519): the holder's, fresh or already held
|
|
850
|
+
SeatedStampId text, -- the OwnerKey.StampId this usage seats: one row incarnation, not a key
|
|
851
|
+
-- forever. Minted by the writer inside the redeeming transaction and not
|
|
852
|
+
-- signed (CadreInviteUsage.PeerStampId).
|
|
853
|
+
GrantSig text, -- by the grant's private key over the 'redeem' digest: proof of possession
|
|
854
|
+
OwnerSig text, -- by SeatedKey over the 'consent' digest: the holder holds the key it seats
|
|
855
|
+
constraint InsertOnly check on update, delete (false),
|
|
856
|
+
-- The grant is read from the pre-transaction snapshot, so a grant cannot be seated and
|
|
857
|
+
-- redeemed in one transaction (the grant branch of OwnerKey.Authorized rests on that).
|
|
858
|
+
-- NOTE: accepted tradeoff — the use cap counts committed usage, so two holders of one
|
|
859
|
+
-- single-use grant redeeming on different machines may both be seated until merge, and
|
|
860
|
+
-- after merge both rows stand (CadreInviteUsage.Authorized). Serializing would need
|
|
861
|
+
-- cross-machine coordination the control plane does not have; the mitigations are the
|
|
862
|
+
-- defaults the writer sets (single use and a 15-minute expiry, a longer lifetime only
|
|
863
|
+
-- when the user chooses one) and the owner seeing the extra key in the owner-key list
|
|
864
|
+
-- and removing it. Revisit if the control plane gains a cross-machine sequencer. An
|
|
865
|
+
-- issuer removed since issuing takes its outstanding grants with it (the
|
|
866
|
+
-- committed.OwnerKey clause, which a tombstone alone satisfies); keys it already
|
|
867
|
+
-- seated stay owners.
|
|
868
|
+
constraint Authorized check on insert (
|
|
869
|
+
exists (
|
|
870
|
+
select 1 from committed.OwnerGrant G
|
|
871
|
+
where G.Key = new.GrantKey
|
|
872
|
+
and not exists (select 1 from Revocation R where R.TableName = 'OwnerGrant' and R.StampId = G.StampId)
|
|
873
|
+
and (G.ExpiresAt is null or G.ExpiresAt > context.Now)
|
|
874
|
+
and (G.TotalUses is null or G.TotalUses > (select count(1) from committed.OwnerGrantUsage U where U.GrantKey = new.GrantKey))
|
|
875
|
+
and exists (select 1 from committed.OwnerKey K where K.Key = G.IssuerKey and not exists (select 1 from Revocation R where R.TableName = 'OwnerKey' and R.StampId = K.StampId))
|
|
876
|
+
)
|
|
877
|
+
),
|
|
878
|
+
-- Verified against the grant key itself: the member writing the row can check this
|
|
879
|
+
-- signature but, holding only the public half, cannot produce it.
|
|
880
|
+
constraint GrantPossessed check on insert (
|
|
881
|
+
verify(digest('CadreControl.OwnerGrantUsage', 'redeem', party_id(), new.GrantKey, new.UsageStampId, new.SeatedKey),
|
|
882
|
+
new.GrantSig, new.GrantKey, 'ed25519')
|
|
883
|
+
),
|
|
884
|
+
-- The holder proves it holds the key being seated (CadreInviteUsage.PeerConsented).
|
|
885
|
+
constraint OwnerConsented check on insert (
|
|
886
|
+
verify(digest('CadreControl.OwnerGrantUsage', 'consent', party_id(), new.GrantKey, new.UsageStampId, new.SeatedKey),
|
|
887
|
+
new.OwnerSig, new.SeatedKey, 'ed25519')
|
|
888
|
+
),
|
|
889
|
+
-- Deferred, so the same-transaction OwnerKey insert counts: a usage row can never be
|
|
890
|
+
-- held in reserve to seat a row later (CadreInviteUsage.PeerExists).
|
|
891
|
+
constraint SeatedExists check (
|
|
892
|
+
exists (select 1 from OwnerKey K where K.Key = new.SeatedKey and K.StampId = new.SeatedStampId)
|
|
893
|
+
)
|
|
894
|
+
) with context (Now datetime);
|
|
895
|
+
|
|
896
|
+
-- Serves the cap count above and the liveness reads (cadre-core countOwnerGrantUsage,
|
|
897
|
+
-- listOwnerGrantStatuses) on an append-only table, as CadreInviteUsageByInvite does.
|
|
898
|
+
index OwnerGrantUsageByGrant on OwnerGrantUsage (GrantKey);
|
|
899
|
+
|
|
749
900
|
-- Append-only retirement record for the stamps of removed rows of every guarded table, with
|
|
750
901
|
-- the removed row's key. Every append is owner-signed, so the growth surface is the owner
|
|
751
902
|
-- keys. One singleton marker row, ('Revocation', 'ledger', 'opened'), retires nothing: an
|
|
752
903
|
-- owner's connected reconcile pass files it (ControlDatabase.openRevocationLedger) so this
|
|
753
904
|
-- table is never a never-written block, which the storage layer would consult the cohort
|
|
754
905
|
-- for on every guarded insert and membership lookup. Readers filter on their own guarded
|
|
755
|
-
-- TableName, and queryRevocations skips it. A 'CadreInvite' row withdraws
|
|
756
|
-
-- whose row stays (
|
|
906
|
+
-- TableName, and queryRevocations skips it. A 'CadreInvite' or 'OwnerGrant' row withdraws
|
|
907
|
+
-- an invitation or a grant whose row stays (the table comments).
|
|
757
908
|
table Revocation (
|
|
758
909
|
TableName text, -- 'OwnerKey' | 'ValidationKey' | 'Strand' | 'StrandPartyKey' | 'JoinedStrand' |
|
|
759
|
-
-- 'JoinRequest' | 'CadrePeer' | 'DeviceToken' | 'CadreInvite'
|
|
760
|
-
-- for the marker
|
|
910
|
+
-- 'JoinRequest' | 'CadrePeer' | 'DeviceToken' | 'CadreInvite' | 'OwnerGrant', or
|
|
911
|
+
-- 'Revocation' for the marker
|
|
761
912
|
RowKey text, -- primary key of the removed row
|
|
762
913
|
StampId text, -- the retired stamp
|
|
763
914
|
ReissuedAt integer default 0, -- bumped by an owner-signed re-issue so a tombstone committed while the
|
|
@@ -785,9 +936,9 @@ declare schema CadreControl {
|
|
|
785
936
|
-- counts). Keyed on the stamp, not RowKey: a node that converges on a re-admission before
|
|
786
937
|
-- the earlier removal's tombstone must still accept that tombstone. Retiring a stamp that
|
|
787
938
|
-- never existed is harmless: stamps carry 128 random bits (generateStampId). For
|
|
788
|
-
-- 'CadreInvite' there is no row-gone test: a tombstone there is a
|
|
789
|
-
-- row stays (
|
|
790
|
-
-- nothing else under 'Revocation'.
|
|
939
|
+
-- 'CadreInvite' and 'OwnerGrant' there is no row-gone test: a tombstone there is a
|
|
940
|
+
-- withdrawal, and the row stays (the table comments). The last branch admits the marker
|
|
941
|
+
-- row and nothing else under 'Revocation'.
|
|
791
942
|
constraint RowIsGone check on insert (
|
|
792
943
|
(new.TableName = 'OwnerKey' and not exists (select 1 from OwnerKey K where K.StampId = new.StampId))
|
|
793
944
|
or (new.TableName = 'CadrePeer' and not exists (select 1 from CadrePeer P where P.StampId = new.StampId))
|
|
@@ -798,6 +949,7 @@ declare schema CadreControl {
|
|
|
798
949
|
or (new.TableName = 'JoinRequest' and not exists (select 1 from JoinRequest J where J.StampId = new.StampId))
|
|
799
950
|
or (new.TableName = 'DeviceToken' and not exists (select 1 from DeviceToken D where D.StampId = new.StampId))
|
|
800
951
|
or (new.TableName = 'CadreInvite')
|
|
952
|
+
or (new.TableName = 'OwnerGrant')
|
|
801
953
|
or (new.TableName = 'Revocation' and new.RowKey = 'ledger' and new.StampId = 'opened')
|
|
802
954
|
),
|
|
803
955
|
-- Owner-signed over the whole row under its own domain tag, so the delete's 'remove'
|
|
@@ -822,8 +974,40 @@ declare schema CadreControl {
|
|
|
822
974
|
context.Signature, A.Key, 'ed25519'))
|
|
823
975
|
)
|
|
824
976
|
) with context (OwnerKey text, Signature text);
|
|
825
|
-
}
|
|
977
|
+
}`;
|
|
978
|
+
/** The name the control schema is declared under; Quereus compares schema names without regard to case. */
|
|
979
|
+
export const CONTROL_SCHEMA_NAME = 'CadreControl';
|
|
980
|
+
/** The statement that applies {@link CONTROL_SCHEMA_DECLARATION}, run only after the store has been checked against it. */
|
|
981
|
+
export const APPLY_CONTROL_SCHEMA = `apply schema ${CONTROL_SCHEMA_NAME};`;
|
|
982
|
+
/** The whole control schema as `schemas/control.qsql` holds it: the declaration, then the apply. */
|
|
983
|
+
export const CONTROL_SCHEMA = `${CONTROL_SCHEMA_DECLARATION}
|
|
826
984
|
|
|
827
|
-
|
|
985
|
+
${APPLY_CONTROL_SCHEMA}
|
|
828
986
|
`;
|
|
987
|
+
/**
|
|
988
|
+
* The declaration statement of a control schema file (`ControlDatabaseConfig.schemaPath`),
|
|
989
|
+
* cut from the file's own text.
|
|
990
|
+
*
|
|
991
|
+
* Refuses a file that is anything other than one `declare schema CadreControl { … }`
|
|
992
|
+
* followed by one plain `apply schema CadreControl` — the shape of {@link CONTROL_SCHEMA}.
|
|
993
|
+
* `loadSchema` runs its own {@link APPLY_CONTROL_SCHEMA} once the store has been checked,
|
|
994
|
+
* so any other statement in the file, or an option on its apply, would be dropped or run
|
|
995
|
+
* unchecked.
|
|
996
|
+
*/
|
|
997
|
+
export function controlSchemaFileDeclaration(source) {
|
|
998
|
+
const statements = new Parser().parseAll(source);
|
|
999
|
+
const [declaration, apply] = statements;
|
|
1000
|
+
if (statements.length !== 2
|
|
1001
|
+
|| declaration.type !== 'declareSchema' || !isControlSchemaName(declaration.schemaName)
|
|
1002
|
+
|| apply.type !== 'applySchema' || !isControlSchemaName(apply.schemaName)
|
|
1003
|
+
|| apply.options !== undefined || apply.toVersion !== undefined || apply.withSeed === true
|
|
1004
|
+
|| declaration.loc === undefined) {
|
|
1005
|
+
throw new Error(`A control schema file must hold exactly \`declare schema ${CONTROL_SCHEMA_NAME} { … }\` ` +
|
|
1006
|
+
`followed by \`${APPLY_CONTROL_SCHEMA}\`, the shape of schemas/control.qsql.`);
|
|
1007
|
+
}
|
|
1008
|
+
return source.slice(declaration.loc.start.offset, declaration.loc.end.offset);
|
|
1009
|
+
}
|
|
1010
|
+
function isControlSchemaName(name) {
|
|
1011
|
+
return name?.toLowerCase() === CONTROL_SCHEMA_NAME.toLowerCase();
|
|
1012
|
+
}
|
|
829
1013
|
//# sourceMappingURL=control-schema.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control-schema.js","sourceRoot":"","sources":["../src/control-schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG
|
|
1
|
+
{"version":3,"file":"control-schema.js","sourceRoot":"","sources":["../src/control-schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -31,7 +31,7 @@ import type { ControlRetryOptions } from './control-retry.js';
|
|
|
31
31
|
* TWO policies ship from here, and the split is deliberate: the default
|
|
32
32
|
* ({@link isRetriableControlWriteFailure}, {@link CONTROL_WRITE_ATTEMPTS}) sits under every
|
|
33
33
|
* control write, and {@link SCHEMA_INIT_RETRY_POLICY} is opted into by
|
|
34
|
-
* `ControlDatabase.
|
|
34
|
+
* `ControlDatabase.applyControlSchema` alone. The widened one absorbs one extra failure class whose
|
|
35
35
|
* re-run safety holds for schema DDL and NOT for writes in general; anything added to the default
|
|
36
36
|
* list must be safe for all ~19 callers.
|
|
37
37
|
*
|
|
@@ -212,7 +212,7 @@ export declare function isUncommittedTransactorAggregate(message: string): boole
|
|
|
212
212
|
export declare function isRetriableControlWriteFailure(error: unknown): boolean;
|
|
213
213
|
/**
|
|
214
214
|
* {@link isRetriableControlWriteFailure} widened by exactly one class — the self-coordination
|
|
215
|
-
* grace refusal ({@link RETRIABLE_SCHEMA_INIT_MATCHERS}) — for `ControlDatabase.
|
|
215
|
+
* grace refusal ({@link RETRIABLE_SCHEMA_INIT_MATCHERS}) — for `ControlDatabase.applyControlSchema`.
|
|
216
216
|
*
|
|
217
217
|
* Opt-in per call site, via {@link SCHEMA_INIT_RETRY_POLICY}. Every other control write keeps the
|
|
218
218
|
* default classifier untouched.
|
|
@@ -230,7 +230,7 @@ export declare function isRetriableSchemaInitFailure(error: unknown): boolean;
|
|
|
230
230
|
*/
|
|
231
231
|
export type ControlWriteRetryOptions = ControlRetryOptions;
|
|
232
232
|
/**
|
|
233
|
-
* The one non-default retry policy: `ControlDatabase.
|
|
233
|
+
* The one non-default retry policy: `ControlDatabase.applyControlSchema`'s distributed DDL, which
|
|
234
234
|
* additionally absorbs optimystic's self-coordination grace refusal and gets more attempts over a
|
|
235
235
|
* longer backoff to do it (see {@link SCHEMA_INIT_ATTEMPTS} and
|
|
236
236
|
* {@link SCHEMA_INIT_RETRY_DELAYS_MS}). Still bounded by the shared
|
|
@@ -238,8 +238,8 @@ export type ControlWriteRetryOptions = ControlRetryOptions;
|
|
|
238
238
|
*
|
|
239
239
|
* NOTE: exactly one call site opts in today, and the re-run safety this policy assumes is that
|
|
240
240
|
* site's, not a general property — `apply schema` is a diff, and a failed apply is unwound whole
|
|
241
|
-
* and verified against the pre-apply catalog (full argument at the `
|
|
242
|
-
* `control-database.ts`). A second opt-in must re-derive that argument for its own write body
|
|
241
|
+
* and verified against the pre-apply catalog (full argument at the `applyControlSchema` call site
|
|
242
|
+
* in `control-database.ts`). A second opt-in must re-derive that argument for its own write body
|
|
243
243
|
* first; if this policy ever grows a third consumer, rename it for what the callers share rather
|
|
244
244
|
* than widening it by default.
|
|
245
245
|
*/
|
|
@@ -33,7 +33,7 @@ import { causeChain, chainMessages, retryControlOperation } from './control-retr
|
|
|
33
33
|
* TWO policies ship from here, and the split is deliberate: the default
|
|
34
34
|
* ({@link isRetriableControlWriteFailure}, {@link CONTROL_WRITE_ATTEMPTS}) sits under every
|
|
35
35
|
* control write, and {@link SCHEMA_INIT_RETRY_POLICY} is opted into by
|
|
36
|
-
* `ControlDatabase.
|
|
36
|
+
* `ControlDatabase.applyControlSchema` alone. The widened one absorbs one extra failure class whose
|
|
37
37
|
* re-run safety holds for schema DDL and NOT for writes in general; anything added to the default
|
|
38
38
|
* list must be safe for all ~19 callers.
|
|
39
39
|
*
|
|
@@ -382,14 +382,16 @@ const RETRIABLE_CONTROL_WRITE_MATCHERS = [
|
|
|
382
382
|
* failed apply is taken back whole — Quereus unwinds every step it ran and verifies the catalog
|
|
383
383
|
* against a pre-apply fingerprint — so a re-run emits exactly the DDL the live catalog is missing.
|
|
384
384
|
* The full argument, including the plugin-side dependency that unwind carries, is at the
|
|
385
|
-
* `
|
|
385
|
+
* `applyControlSchema` call site in `control-database.ts`.
|
|
386
386
|
*
|
|
387
387
|
* RETRIED DELIBERATELY, not by oversight: the failures Quereus cannot take back. When the unwind
|
|
388
388
|
* does not complete — an undo statement threw, the post-unwind catalog did not match the pre-apply
|
|
389
389
|
* fingerprint, that catalog could not be re-collected to check, or a step the differ marks
|
|
390
390
|
* irreversible because it discards data (dropping a table or a column, narrowing a column's type —
|
|
391
|
-
* none of which a `CadreControl`
|
|
392
|
-
*
|
|
391
|
+
* none of which reaches a `CadreControl` apply: a cold store's diff is all creates, and
|
|
392
|
+
* `refuseIncompatibleControlStore` in `control-schema-version.ts` refuses a warm store whose diff
|
|
393
|
+
* holds anything but creates and tag changes before the apply runs) poisoned the journal before it
|
|
394
|
+
* ran, leaving nothing unwound — Quereus keeps the failing step's own message, APPENDS the reason the
|
|
393
395
|
* schema could not be restored, and carries the original as `cause`. So a transient cause
|
|
394
396
|
* underneath still matches here, and neither veto ({@link reportsPossiblyStoredWrite},
|
|
395
397
|
* {@link reportsIndeterminateCommit}) looks for that reason text. Retrying over a partially migrated
|
|
@@ -432,7 +434,7 @@ export function isRetriableControlWriteFailure(error) {
|
|
|
432
434
|
}
|
|
433
435
|
/**
|
|
434
436
|
* {@link isRetriableControlWriteFailure} widened by exactly one class — the self-coordination
|
|
435
|
-
* grace refusal ({@link RETRIABLE_SCHEMA_INIT_MATCHERS}) — for `ControlDatabase.
|
|
437
|
+
* grace refusal ({@link RETRIABLE_SCHEMA_INIT_MATCHERS}) — for `ControlDatabase.applyControlSchema`.
|
|
436
438
|
*
|
|
437
439
|
* Opt-in per call site, via {@link SCHEMA_INIT_RETRY_POLICY}. Every other control write keeps the
|
|
438
440
|
* default classifier untouched.
|
|
@@ -466,7 +468,7 @@ function matchesRetriableFailure(error, matchers) {
|
|
|
466
468
|
return messages.some(message => matchers.some(matches => matches(message)));
|
|
467
469
|
}
|
|
468
470
|
/**
|
|
469
|
-
* The one non-default retry policy: `ControlDatabase.
|
|
471
|
+
* The one non-default retry policy: `ControlDatabase.applyControlSchema`'s distributed DDL, which
|
|
470
472
|
* additionally absorbs optimystic's self-coordination grace refusal and gets more attempts over a
|
|
471
473
|
* longer backoff to do it (see {@link SCHEMA_INIT_ATTEMPTS} and
|
|
472
474
|
* {@link SCHEMA_INIT_RETRY_DELAYS_MS}). Still bounded by the shared
|
|
@@ -474,8 +476,8 @@ function matchesRetriableFailure(error, matchers) {
|
|
|
474
476
|
*
|
|
475
477
|
* NOTE: exactly one call site opts in today, and the re-run safety this policy assumes is that
|
|
476
478
|
* site's, not a general property — `apply schema` is a diff, and a failed apply is unwound whole
|
|
477
|
-
* and verified against the pre-apply catalog (full argument at the `
|
|
478
|
-
* `control-database.ts`). A second opt-in must re-derive that argument for its own write body
|
|
479
|
+
* and verified against the pre-apply catalog (full argument at the `applyControlSchema` call site
|
|
480
|
+
* in `control-database.ts`). A second opt-in must re-derive that argument for its own write body
|
|
479
481
|
* first; if this policy ever grows a third consumer, rename it for what the callers share rather
|
|
480
482
|
* than widening it by default.
|
|
481
483
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control-write-retry.js","sourceRoot":"","sources":["../src/control-write-retry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,6BAA6B,EAAE,uBAAuB,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC9G,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAC3E,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAGtF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC;AAExC;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC;AAEtC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,0NAA0N;AAC1N,MAAM,CAAC,MAAM,6BAA6B,GAAG,KAAM,CAAC;AAEpD;;;;;;GAMG;AACH,MAAM,6BAA6B,GAAsB,CAAC,GAAG,EAAE,IAAK,CAAC,CAAC;AAEtE;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,2BAA2B,GAAsB,CAAC,GAAG,EAAE,GAAG,EAAE,IAAK,EAAE,IAAK,CAAC,CAAC;AAEhF,+FAA+F;AAC/F,MAAM,oBAAoB,GAAG,8BAA8B,CAAC;AAE5D;;;GAGG;AACH,MAAM,wBAAwB,GAAG,SAAS,CAAC;AAE3C;;;GAGG;AACH,MAAM,kBAAkB,GAAG,UAAU,CAAC;AAEtC;;;;;;;;;;;;;GAaG;AACH,MAAM,mCAAmC,GACxC,+EAA+E,CAAC;AAEjF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+EG;AACH,MAAM,UAAU,gCAAgC,CAAC,OAAe;IAC/D,OAAO,oBAAoB,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAAC,CAAC;AACzF,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAS,0BAA0B,CAAC,QAA2B;IAC9D,OAAO,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC,CAAC;AACvE,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,SAAS,0BAA0B,CAAC,KAAuB;IAC1D,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACxB,IAAI,YAAY,uBAAuB;WACpC,CAAC,IAAI,YAAY,eAAe,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC;WACxD,IAAI,YAAY,6BAA6B;WAC7C,IAAI,YAAY,kBAAkB,CAAC,CAAC;AACzC,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,SAAS,gBAAgB,CAAC,IAAW;IACpC,OAAO,IAAI,YAAY,eAAe,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC;AAC/D,CAAC;AAED,mFAAmF;AACnF,SAAS,kCAAkC,CAAC,OAAe;IAC1D,OAAO,mCAAmC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAC1D,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,+BAA+B,GACpC,0FAA0F,CAAC;AAE5F,wFAAwF;AACxF,SAAS,8BAA8B,CAAC,OAAe;IACtD,OAAO,+BAA+B,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACtD,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,gCAAgC,GAA8C;IACnF,gCAAgC;IAChC,kCAAkC;CAClC,CAAC;AAEF
|
|
1
|
+
{"version":3,"file":"control-write-retry.js","sourceRoot":"","sources":["../src/control-write-retry.ts"],"names":[],"mappings":"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"}
|