@substrat-run/adapter-cloudflare 0.2.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/LICENSE +661 -0
- package/dist/checker.d.ts +22 -0
- package/dist/checker.d.ts.map +1 -0
- package/dist/checker.js +128 -0
- package/dist/checker.js.map +1 -0
- package/dist/control-plane-do.d.ts +90 -0
- package/dist/control-plane-do.d.ts.map +1 -0
- package/dist/control-plane-do.js +279 -0
- package/dist/control-plane-do.js.map +1 -0
- package/dist/host.d.ts +34 -0
- package/dist/host.d.ts.map +1 -0
- package/dist/host.js +234 -0
- package/dist/host.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/scope-do.d.ts +21 -0
- package/dist/scope-do.d.ts.map +1 -0
- package/dist/scope-do.js +339 -0
- package/dist/scope-do.js.map +1 -0
- package/dist/serialization.d.ts +17 -0
- package/dist/serialization.d.ts.map +1 -0
- package/dist/serialization.js +22 -0
- package/dist/serialization.js.map +1 -0
- package/dist/sql.d.ts +17 -0
- package/dist/sql.d.ts.map +1 -0
- package/dist/sql.js +24 -0
- package/dist/sql.js.map +1 -0
- package/package.json +44 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checker.d.ts","sourceRoot":"","sources":["../src/checker.ts"],"names":[],"mappings":"AAAA,OAAO,EAQL,KAAK,cAAc,EACpB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAmB9D,UAAU,QAAQ;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,kFAAkF;AAClF,MAAM,WAAW,kBAAkB;IACjC,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC7F,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CAAC;CAC7E;AAED,MAAM,WAAW,aAAa;IAC5B,wEAAwE;IACxE,QAAQ,EAAE,UAAU,CAAC;IACrB,8DAA8D;IAC9D,YAAY,EAAE,kBAAkB,CAAC;CAClC;AAQD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,aAAa,GAAG,iBAAiB,CA2I3E"}
|
package/dist/checker.js
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { objectRef, } from '@substrat-run/contracts';
|
|
2
|
+
/**
|
|
3
|
+
* The built-in constrained relationship-tuple evaluator (design doc §4.2, plan
|
|
4
|
+
* D-23), ported to the Durable-Object split. Identical four-rule algebra to the
|
|
5
|
+
* pure adapter's `createTupleChecker` — role expansion, tenancy-tree
|
|
6
|
+
* inheritance, declared entity parent edges (depth ≤ 4), membership — no
|
|
7
|
+
* negation, no configurable rewrites. Every allow carries its tuple proof.
|
|
8
|
+
*
|
|
9
|
+
* Tuple placement mirrors the pure adapter, split across DOs: scope-level and
|
|
10
|
+
* entity tuples live in THIS ScopeDO's SQLite (`_substrat_tuples`, read
|
|
11
|
+
* synchronously); tenant-level assignments/grants, roles, and org membership
|
|
12
|
+
* live in the ControlPlaneDO and are reached over RPC (async). The whole
|
|
13
|
+
* evaluation still runs inside the ScopeDO's serialization domain, so
|
|
14
|
+
* check-after-write consistency holds — the "no zookies" property.
|
|
15
|
+
*/
|
|
16
|
+
const ENTITY_WALK_DEPTH = 4;
|
|
17
|
+
const t = (subject, relation, object) => ({
|
|
18
|
+
subject: objectRef.parse(subject),
|
|
19
|
+
relation,
|
|
20
|
+
object: objectRef.parse(object),
|
|
21
|
+
});
|
|
22
|
+
export function createDoTupleChecker(deps) {
|
|
23
|
+
const scopeTuples = (subject, relationPrefix) => deps.scopeSql
|
|
24
|
+
.exec(`SELECT subject, relation, object, expires_at FROM _substrat_tuples
|
|
25
|
+
WHERE subject = ? AND relation LIKE ?`, subject, `${relationPrefix}%`)
|
|
26
|
+
.toArray();
|
|
27
|
+
const live = (row, now) => row.expires_at === null || row.expires_at > now;
|
|
28
|
+
return {
|
|
29
|
+
async check(principal, permission, node, entity) {
|
|
30
|
+
const now = new Date().toISOString();
|
|
31
|
+
const deny = { allowed: false, checked: permission, node };
|
|
32
|
+
const cp = deps.controlPlane;
|
|
33
|
+
// Rule 4 — membership: the subject set is the principal plus its orgs.
|
|
34
|
+
const subjects = [{ ref: `principal:${principal}` }];
|
|
35
|
+
for (const m of await cp.tenantTuples(node.tenantId, `principal:${principal}`, 'member')) {
|
|
36
|
+
if (m.relation === 'member' && live(m, now)) {
|
|
37
|
+
subjects.push({ ref: m.object, via: t(m.subject, m.relation, m.object) });
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// Inheritance (rule 2): a scope check also consults tenant-level tuples.
|
|
41
|
+
const nodeObjects = node.scopeId
|
|
42
|
+
? [
|
|
43
|
+
{ obj: `scope:${node.scopeId}`, scoped: true },
|
|
44
|
+
{ obj: `tenant:${node.tenantId}`, scoped: false },
|
|
45
|
+
]
|
|
46
|
+
: [{ obj: `tenant:${node.tenantId}`, scoped: false }];
|
|
47
|
+
const tuplesFor = async (subject, prefix, scoped) => scoped ? scopeTuples(subject, prefix) : cp.tenantTuples(node.tenantId, subject, prefix);
|
|
48
|
+
for (const nodeObj of nodeObjects) {
|
|
49
|
+
for (const subject of subjects) {
|
|
50
|
+
// Rule 1 — role expansion.
|
|
51
|
+
for (const row of await tuplesFor(subject.ref, 'role:', nodeObj.scoped)) {
|
|
52
|
+
if (row.object !== nodeObj.obj || !live(row, now))
|
|
53
|
+
continue;
|
|
54
|
+
const roleKey = row.relation.slice('role:'.length);
|
|
55
|
+
const role = await cp.getRole(node.tenantId, roleKey);
|
|
56
|
+
if (role?.permissions.includes(permission)) {
|
|
57
|
+
return {
|
|
58
|
+
allowed: true,
|
|
59
|
+
proof: [
|
|
60
|
+
...(subject.via ? [subject.via] : []),
|
|
61
|
+
t(row.subject, row.relation, row.object),
|
|
62
|
+
t(`role:${roleKey}`, `granted:${permission}`, nodeObj.obj),
|
|
63
|
+
],
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// Direct grants at the node.
|
|
68
|
+
for (const row of await tuplesFor(subject.ref, `granted:${permission}`, nodeObj.scoped)) {
|
|
69
|
+
if (row.object === nodeObj.obj &&
|
|
70
|
+
row.relation === `granted:${permission}` &&
|
|
71
|
+
live(row, now)) {
|
|
72
|
+
return {
|
|
73
|
+
allowed: true,
|
|
74
|
+
proof: [
|
|
75
|
+
...(subject.via ? [subject.via] : []),
|
|
76
|
+
t(row.subject, row.relation, row.object),
|
|
77
|
+
],
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// Rule 3 — entity walk along declared parent edges (entity grants are
|
|
84
|
+
// scope-local by construction).
|
|
85
|
+
if (entity) {
|
|
86
|
+
let frontier = [{ ref: `${entity.entityType}:${entity.entityId}`, chain: [] }];
|
|
87
|
+
for (let depth = 0; depth <= ENTITY_WALK_DEPTH && frontier.length > 0; depth++) {
|
|
88
|
+
// grant lookup at current frontier objects
|
|
89
|
+
for (const candidate of frontier) {
|
|
90
|
+
for (const subject of subjects) {
|
|
91
|
+
const grant = deps.scopeSql
|
|
92
|
+
.exec(`SELECT subject, relation, object, expires_at FROM _substrat_tuples
|
|
93
|
+
WHERE subject = ? AND relation = ? AND object = ?`, subject.ref, `granted:${permission}`, candidate.ref)
|
|
94
|
+
.toArray()[0];
|
|
95
|
+
if (grant && live(grant, now)) {
|
|
96
|
+
return {
|
|
97
|
+
allowed: true,
|
|
98
|
+
proof: [
|
|
99
|
+
...(subject.via ? [subject.via] : []),
|
|
100
|
+
...candidate.chain,
|
|
101
|
+
t(grant.subject, grant.relation, grant.object),
|
|
102
|
+
],
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// expand one level of parents
|
|
108
|
+
const next = [];
|
|
109
|
+
for (const candidate of frontier) {
|
|
110
|
+
const parents = deps.scopeSql
|
|
111
|
+
.exec(`SELECT subject, relation, object, expires_at FROM _substrat_tuples
|
|
112
|
+
WHERE subject = ? AND relation = 'parent'`, candidate.ref)
|
|
113
|
+
.toArray();
|
|
114
|
+
for (const p of parents) {
|
|
115
|
+
next.push({
|
|
116
|
+
ref: p.object,
|
|
117
|
+
chain: [...candidate.chain, t(p.subject, 'parent', p.object)],
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
frontier = next;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return deny;
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=checker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checker.js","sourceRoot":"","sources":["../src/checker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { DurableObject } from 'cloudflare:workers';
|
|
2
|
+
import type { AdminLogEntry, RoleDefinition, ScopeStatus, Tenant, TenantStatus } from '@substrat-run/contracts';
|
|
3
|
+
/**
|
|
4
|
+
* The durable directory (control-plane.md §4). One singleton DO, backed by its
|
|
5
|
+
* own SQLite, is the WHOLE directory: the tenant registry, scope lifecycle,
|
|
6
|
+
* roles, tenant-level relation tuples, entitlements, identities, and the admin
|
|
7
|
+
* audit log. The coordinator (`CloudflareScopeHost`) is a stateless async router
|
|
8
|
+
* that `await`s RPCs to here — nothing directory-shaped lives in the Worker
|
|
9
|
+
* isolate anymore. A ScopeDO's permission checker reads `getRole`/`tenantTuples`
|
|
10
|
+
* from here for the tenant-level rows it cannot reach locally.
|
|
11
|
+
*
|
|
12
|
+
* Every method is synchronous DO SQL; the RPC layer makes them awaitable. The
|
|
13
|
+
* fail-closed cases THROW plain `Error`s (never a ZodError — the coordinator does
|
|
14
|
+
* all the Zod parsing before calling in), so the message survives the RPC hop.
|
|
15
|
+
* Effect methods return what the coordinator needs for the audit entry to spare
|
|
16
|
+
* it a read round-trip.
|
|
17
|
+
*
|
|
18
|
+
* Tuple placement follows the pure adapter's checker verbatim (§4.2): scope +
|
|
19
|
+
* entity tuples in the ScopeDO, tenant tuples + roles here.
|
|
20
|
+
*/
|
|
21
|
+
interface TupleRow {
|
|
22
|
+
subject: string;
|
|
23
|
+
relation: string;
|
|
24
|
+
object: string;
|
|
25
|
+
expires_at: string | null;
|
|
26
|
+
}
|
|
27
|
+
/** The shape the coordinator hands `recordAdmin`; before/after are arbitrary JSON. */
|
|
28
|
+
export interface AdminEntryInput {
|
|
29
|
+
id: string;
|
|
30
|
+
actor: string;
|
|
31
|
+
action: string;
|
|
32
|
+
tenantId: string;
|
|
33
|
+
scopeId: string | null;
|
|
34
|
+
vertical: string | null;
|
|
35
|
+
before: unknown;
|
|
36
|
+
after: unknown;
|
|
37
|
+
at: string;
|
|
38
|
+
}
|
|
39
|
+
export declare class ControlPlaneDO extends DurableObject {
|
|
40
|
+
private readonly sql;
|
|
41
|
+
constructor(ctx: DurableObjectState, env: unknown);
|
|
42
|
+
private mapTenant;
|
|
43
|
+
private readTenant;
|
|
44
|
+
/** INSERT OR IGNORE; return the new tenant, or null if it already existed. */
|
|
45
|
+
createTenant(id: string, slug: string, name: string, createdAt: string): Tenant | null;
|
|
46
|
+
/** Throw if absent; else UPDATE and return the previous status. */
|
|
47
|
+
setTenantStatus(tenantId: string, status: TenantStatus): string;
|
|
48
|
+
getTenant(tenantId: string): Tenant | undefined;
|
|
49
|
+
listTenants(): Tenant[];
|
|
50
|
+
/**
|
|
51
|
+
* Mandatory active tenant: a scope with no tenant record is the "tenant is an
|
|
52
|
+
* FK string" hole the registry closes — fail closed. INSERT OR IGNORE the
|
|
53
|
+
* scope with status 'active'; return whether it was newly created.
|
|
54
|
+
*/
|
|
55
|
+
provisionScope(tenantId: string, scopeId: string, storageShape: string, jurisdiction: string | null, createdAt: string): boolean;
|
|
56
|
+
/**
|
|
57
|
+
* The getScope gate (control-plane.md §4.1/§4.2): validate the scope belongs
|
|
58
|
+
* to the tenant and both records are active, or throw the fail-closed reason.
|
|
59
|
+
*/
|
|
60
|
+
validateScopeAccess(tenantId: string, scopeId: string): void;
|
|
61
|
+
/**
|
|
62
|
+
* Validate ownership, enforce the legal transition graph (fail closed on an
|
|
63
|
+
* illegal one), flip the status. Returns the previous status for the audit.
|
|
64
|
+
* `action` rides along only to name the illegal-transition message.
|
|
65
|
+
*/
|
|
66
|
+
transitionScope(tenantId: string, scopeId: string, from: string[], to: ScopeStatus, action: string): string;
|
|
67
|
+
/** INSERT OR REPLACE; return the previous role (for the audit `before`) or null. */
|
|
68
|
+
defineRole(tenantId: string, role: RoleDefinition): RoleDefinition | null;
|
|
69
|
+
getRole(tenantId: string, key: string): RoleDefinition | undefined;
|
|
70
|
+
writeTenantTuple(tenantId: string, subject: string, relation: string, object: string, expiresAt: string | null): void;
|
|
71
|
+
tenantTuples(tenantId: string, subject: string, relationPrefix: string): TupleRow[];
|
|
72
|
+
/** INSERT OR IGNORE; return whether it changed (idempotent). */
|
|
73
|
+
grantEntitlement(tenantId: string, key: string): boolean;
|
|
74
|
+
/** DELETE; return whether it changed (idempotent). */
|
|
75
|
+
revokeEntitlement(tenantId: string, key: string): boolean;
|
|
76
|
+
tenantHoldsEntitlement(tenantId: string, key: string): boolean;
|
|
77
|
+
listEntitlements(tenantId: string): string[];
|
|
78
|
+
/** INSERT OR IGNORE; return whether it changed (idempotent). */
|
|
79
|
+
linkIdentity(provider: string, externalId: string, principal: string, tenantId: string, scopeId: string | null, createdAt: string): boolean;
|
|
80
|
+
resolveIdentity(provider: string, externalId: string): {
|
|
81
|
+
principal: string;
|
|
82
|
+
tenantId: string;
|
|
83
|
+
scopeId: string | null;
|
|
84
|
+
} | undefined;
|
|
85
|
+
/** Append one audit row. before/after are arbitrary JSON, stringified here. */
|
|
86
|
+
recordAdmin(entry: AdminEntryInput): void;
|
|
87
|
+
auditLog(tenantId: string | null): AdminLogEntry[];
|
|
88
|
+
}
|
|
89
|
+
export {};
|
|
90
|
+
//# sourceMappingURL=control-plane-do.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"control-plane-do.d.ts","sourceRoot":"","sources":["../src/control-plane-do.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import { DurableObject } from 'cloudflare:workers';
|
|
2
|
+
const DIRECTORY_DDL = `
|
|
3
|
+
CREATE TABLE IF NOT EXISTS tenants (
|
|
4
|
+
tenant_id TEXT PRIMARY KEY,
|
|
5
|
+
slug TEXT NOT NULL,
|
|
6
|
+
name TEXT NOT NULL,
|
|
7
|
+
status TEXT NOT NULL DEFAULT 'active',
|
|
8
|
+
created_at TEXT NOT NULL
|
|
9
|
+
);
|
|
10
|
+
CREATE TABLE IF NOT EXISTS scopes (
|
|
11
|
+
scope_id TEXT PRIMARY KEY,
|
|
12
|
+
tenant_id TEXT NOT NULL,
|
|
13
|
+
storage_shape TEXT NOT NULL DEFAULT 'A',
|
|
14
|
+
jurisdiction TEXT,
|
|
15
|
+
status TEXT NOT NULL DEFAULT 'active',
|
|
16
|
+
schema_version TEXT NOT NULL DEFAULT '0',
|
|
17
|
+
created_at TEXT NOT NULL
|
|
18
|
+
);
|
|
19
|
+
CREATE TABLE IF NOT EXISTS _substrat_tenant_tuples (
|
|
20
|
+
tenant_id TEXT NOT NULL,
|
|
21
|
+
subject TEXT NOT NULL,
|
|
22
|
+
relation TEXT NOT NULL,
|
|
23
|
+
object TEXT NOT NULL,
|
|
24
|
+
expires_at TEXT,
|
|
25
|
+
PRIMARY KEY (tenant_id, subject, relation, object)
|
|
26
|
+
);
|
|
27
|
+
CREATE TABLE IF NOT EXISTS _substrat_roles (
|
|
28
|
+
tenant_id TEXT NOT NULL,
|
|
29
|
+
role_key TEXT NOT NULL,
|
|
30
|
+
permissions TEXT NOT NULL,
|
|
31
|
+
source TEXT NOT NULL,
|
|
32
|
+
PRIMARY KEY (tenant_id, role_key)
|
|
33
|
+
);
|
|
34
|
+
CREATE TABLE IF NOT EXISTS _substrat_entitlements (
|
|
35
|
+
tenant_id TEXT NOT NULL,
|
|
36
|
+
entitlement_key TEXT NOT NULL,
|
|
37
|
+
PRIMARY KEY (tenant_id, entitlement_key)
|
|
38
|
+
);
|
|
39
|
+
CREATE TABLE IF NOT EXISTS _substrat_identities (
|
|
40
|
+
provider TEXT NOT NULL,
|
|
41
|
+
external_id TEXT NOT NULL,
|
|
42
|
+
principal_id TEXT NOT NULL,
|
|
43
|
+
tenant_id TEXT NOT NULL,
|
|
44
|
+
scope_id TEXT,
|
|
45
|
+
created_at TEXT NOT NULL,
|
|
46
|
+
PRIMARY KEY (provider, external_id)
|
|
47
|
+
);
|
|
48
|
+
CREATE TABLE IF NOT EXISTS _substrat_admin_log (
|
|
49
|
+
id TEXT PRIMARY KEY,
|
|
50
|
+
actor TEXT NOT NULL,
|
|
51
|
+
action TEXT NOT NULL,
|
|
52
|
+
tenant_id TEXT NOT NULL,
|
|
53
|
+
scope_id TEXT,
|
|
54
|
+
vertical TEXT,
|
|
55
|
+
before TEXT,
|
|
56
|
+
after TEXT,
|
|
57
|
+
at TEXT NOT NULL
|
|
58
|
+
);
|
|
59
|
+
`;
|
|
60
|
+
export class ControlPlaneDO extends DurableObject {
|
|
61
|
+
sql;
|
|
62
|
+
constructor(ctx, env) {
|
|
63
|
+
super(ctx, env);
|
|
64
|
+
this.sql = ctx.storage.sql;
|
|
65
|
+
for (const stmt of DIRECTORY_DDL.split(';')) {
|
|
66
|
+
const s = stmt.trim();
|
|
67
|
+
if (s)
|
|
68
|
+
this.sql.exec(s);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// -- tenant registry (control-plane.md §4.1) --------------------------------
|
|
72
|
+
mapTenant(r) {
|
|
73
|
+
return {
|
|
74
|
+
id: r.tenant_id,
|
|
75
|
+
slug: r.slug,
|
|
76
|
+
name: r.name,
|
|
77
|
+
status: r.status,
|
|
78
|
+
createdAt: r.created_at,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
readTenant(tenantId) {
|
|
82
|
+
const row = this.sql
|
|
83
|
+
.exec('SELECT * FROM tenants WHERE tenant_id = ?', tenantId)
|
|
84
|
+
.toArray()[0];
|
|
85
|
+
return row ? this.mapTenant(row) : undefined;
|
|
86
|
+
}
|
|
87
|
+
/** INSERT OR IGNORE; return the new tenant, or null if it already existed. */
|
|
88
|
+
createTenant(id, slug, name, createdAt) {
|
|
89
|
+
if (this.readTenant(id))
|
|
90
|
+
return null; // idempotent — nothing created
|
|
91
|
+
this.sql.exec(`INSERT OR IGNORE INTO tenants (tenant_id, slug, name, status, created_at)
|
|
92
|
+
VALUES (?, ?, ?, 'active', ?)`, id, slug, name, createdAt);
|
|
93
|
+
return this.readTenant(id) ?? null;
|
|
94
|
+
}
|
|
95
|
+
/** Throw if absent; else UPDATE and return the previous status. */
|
|
96
|
+
setTenantStatus(tenantId, status) {
|
|
97
|
+
const before = this.readTenant(tenantId);
|
|
98
|
+
if (!before)
|
|
99
|
+
throw new Error(`unknown tenant: ${tenantId}`);
|
|
100
|
+
this.sql.exec('UPDATE tenants SET status = ? WHERE tenant_id = ?', status, tenantId);
|
|
101
|
+
return before.status;
|
|
102
|
+
}
|
|
103
|
+
getTenant(tenantId) {
|
|
104
|
+
return this.readTenant(tenantId);
|
|
105
|
+
}
|
|
106
|
+
listTenants() {
|
|
107
|
+
return this.sql.exec('SELECT * FROM tenants ORDER BY tenant_id').toArray().map((r) => this.mapTenant(r));
|
|
108
|
+
}
|
|
109
|
+
// -- scope lifecycle (control-plane.md §4.1/§4.2) ---------------------------
|
|
110
|
+
/**
|
|
111
|
+
* Mandatory active tenant: a scope with no tenant record is the "tenant is an
|
|
112
|
+
* FK string" hole the registry closes — fail closed. INSERT OR IGNORE the
|
|
113
|
+
* scope with status 'active'; return whether it was newly created.
|
|
114
|
+
*/
|
|
115
|
+
provisionScope(tenantId, scopeId, storageShape, jurisdiction, createdAt) {
|
|
116
|
+
const tenantRow = this.sql
|
|
117
|
+
.exec('SELECT status FROM tenants WHERE tenant_id = ?', tenantId)
|
|
118
|
+
.toArray()[0];
|
|
119
|
+
if (!tenantRow) {
|
|
120
|
+
throw new Error(`cannot provision scope under unknown tenant: ${tenantId}`);
|
|
121
|
+
}
|
|
122
|
+
if (tenantRow.status !== 'active') {
|
|
123
|
+
throw new Error(`cannot provision scope under non-active tenant (status: ${tenantRow.status}): ${tenantId}`);
|
|
124
|
+
}
|
|
125
|
+
const existed = this.sql.exec('SELECT 1 FROM scopes WHERE scope_id = ?', scopeId).toArray()[0] !== undefined;
|
|
126
|
+
if (!existed) {
|
|
127
|
+
this.sql.exec(`INSERT OR IGNORE INTO scopes (scope_id, tenant_id, storage_shape, jurisdiction, status, created_at)
|
|
128
|
+
VALUES (?, ?, ?, ?, 'active', ?)`, scopeId, tenantId, storageShape, jurisdiction, createdAt);
|
|
129
|
+
}
|
|
130
|
+
return !existed;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* The getScope gate (control-plane.md §4.1/§4.2): validate the scope belongs
|
|
134
|
+
* to the tenant and both records are active, or throw the fail-closed reason.
|
|
135
|
+
*/
|
|
136
|
+
validateScopeAccess(tenantId, scopeId) {
|
|
137
|
+
const row = this.sql
|
|
138
|
+
.exec('SELECT tenant_id, status FROM scopes WHERE scope_id = ?', scopeId)
|
|
139
|
+
.toArray()[0];
|
|
140
|
+
if (!row || row.tenant_id !== tenantId) {
|
|
141
|
+
throw new Error(`unknown scope for tenant: (${tenantId}, ${scopeId})`);
|
|
142
|
+
}
|
|
143
|
+
const tenantRow = this.sql
|
|
144
|
+
.exec('SELECT status FROM tenants WHERE tenant_id = ?', tenantId)
|
|
145
|
+
.toArray()[0];
|
|
146
|
+
if (!tenantRow) {
|
|
147
|
+
throw new Error(`scope has no tenant record: (${tenantId}, ${scopeId})`);
|
|
148
|
+
}
|
|
149
|
+
if (tenantRow.status !== 'active') {
|
|
150
|
+
throw new Error(`tenant not active (status: ${tenantRow.status}): ${tenantId}`);
|
|
151
|
+
}
|
|
152
|
+
if (row.status !== 'active') {
|
|
153
|
+
throw new Error(`scope not active (status: ${row.status}): ${scopeId}`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Validate ownership, enforce the legal transition graph (fail closed on an
|
|
158
|
+
* illegal one), flip the status. Returns the previous status for the audit.
|
|
159
|
+
* `action` rides along only to name the illegal-transition message.
|
|
160
|
+
*/
|
|
161
|
+
transitionScope(tenantId, scopeId, from, to, action) {
|
|
162
|
+
const row = this.sql
|
|
163
|
+
.exec('SELECT tenant_id, status FROM scopes WHERE scope_id = ?', scopeId)
|
|
164
|
+
.toArray()[0];
|
|
165
|
+
if (!row || row.tenant_id !== tenantId) {
|
|
166
|
+
throw new Error(`unknown scope for tenant: (${tenantId}, ${scopeId})`);
|
|
167
|
+
}
|
|
168
|
+
if (!from.includes(row.status)) {
|
|
169
|
+
throw new Error(`illegal scope transition for ${action}: ${row.status} → ${to} ` +
|
|
170
|
+
`(allowed from: ${from.join('|')})`);
|
|
171
|
+
}
|
|
172
|
+
this.sql.exec('UPDATE scopes SET status = ? WHERE scope_id = ?', to, scopeId);
|
|
173
|
+
return row.status;
|
|
174
|
+
}
|
|
175
|
+
// -- roles (checker rule 1) -------------------------------------------------
|
|
176
|
+
/** INSERT OR REPLACE; return the previous role (for the audit `before`) or null. */
|
|
177
|
+
defineRole(tenantId, role) {
|
|
178
|
+
const before = this.getRole(tenantId, role.key) ?? null;
|
|
179
|
+
this.sql.exec(`INSERT OR REPLACE INTO _substrat_roles (tenant_id, role_key, permissions, source)
|
|
180
|
+
VALUES (?, ?, ?, ?)`, tenantId, role.key, JSON.stringify(role.permissions), String(role.source));
|
|
181
|
+
return before;
|
|
182
|
+
}
|
|
183
|
+
getRole(tenantId, key) {
|
|
184
|
+
const row = this.sql
|
|
185
|
+
.exec('SELECT role_key, permissions, source FROM _substrat_roles WHERE tenant_id = ? AND role_key = ?', tenantId, key)
|
|
186
|
+
.toArray()[0];
|
|
187
|
+
if (!row)
|
|
188
|
+
return undefined;
|
|
189
|
+
return {
|
|
190
|
+
key: row.role_key,
|
|
191
|
+
permissions: JSON.parse(row.permissions),
|
|
192
|
+
source: row.source,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
// -- tenant-level tuples (checker rules 1, 2, 4) ----------------------------
|
|
196
|
+
writeTenantTuple(tenantId, subject, relation, object, expiresAt) {
|
|
197
|
+
this.sql.exec(`INSERT OR REPLACE INTO _substrat_tenant_tuples
|
|
198
|
+
(tenant_id, subject, relation, object, expires_at)
|
|
199
|
+
VALUES (?, ?, ?, ?, ?)`, tenantId, subject, relation, object, expiresAt);
|
|
200
|
+
}
|
|
201
|
+
tenantTuples(tenantId, subject, relationPrefix) {
|
|
202
|
+
return this.sql
|
|
203
|
+
.exec(`SELECT subject, relation, object, expires_at FROM _substrat_tenant_tuples
|
|
204
|
+
WHERE tenant_id = ? AND subject = ? AND relation LIKE ?`, tenantId, subject, `${relationPrefix}%`)
|
|
205
|
+
.toArray();
|
|
206
|
+
}
|
|
207
|
+
// -- entitlements (control-plane.md §4.3) -----------------------------------
|
|
208
|
+
/** INSERT OR IGNORE; return whether it changed (idempotent). */
|
|
209
|
+
grantEntitlement(tenantId, key) {
|
|
210
|
+
if (this.tenantHoldsEntitlement(tenantId, key))
|
|
211
|
+
return false;
|
|
212
|
+
this.sql.exec(`INSERT OR IGNORE INTO _substrat_entitlements (tenant_id, entitlement_key)
|
|
213
|
+
VALUES (?, ?)`, tenantId, key);
|
|
214
|
+
return true;
|
|
215
|
+
}
|
|
216
|
+
/** DELETE; return whether it changed (idempotent). */
|
|
217
|
+
revokeEntitlement(tenantId, key) {
|
|
218
|
+
if (!this.tenantHoldsEntitlement(tenantId, key))
|
|
219
|
+
return false;
|
|
220
|
+
this.sql.exec('DELETE FROM _substrat_entitlements WHERE tenant_id = ? AND entitlement_key = ?', tenantId, key);
|
|
221
|
+
return true;
|
|
222
|
+
}
|
|
223
|
+
tenantHoldsEntitlement(tenantId, key) {
|
|
224
|
+
return (this.sql
|
|
225
|
+
.exec('SELECT 1 FROM _substrat_entitlements WHERE tenant_id = ? AND entitlement_key = ?', tenantId, key)
|
|
226
|
+
.toArray()[0] !== undefined);
|
|
227
|
+
}
|
|
228
|
+
listEntitlements(tenantId) {
|
|
229
|
+
return this.sql
|
|
230
|
+
.exec('SELECT entitlement_key FROM _substrat_entitlements WHERE tenant_id = ? ORDER BY entitlement_key', tenantId)
|
|
231
|
+
.toArray().map((r) => r.entitlement_key);
|
|
232
|
+
}
|
|
233
|
+
// -- identities (D-16; control-plane.md §6) ---------------------------------
|
|
234
|
+
/** INSERT OR IGNORE; return whether it changed (idempotent). */
|
|
235
|
+
linkIdentity(provider, externalId, principal, tenantId, scopeId, createdAt) {
|
|
236
|
+
const existed = this.sql
|
|
237
|
+
.exec('SELECT 1 FROM _substrat_identities WHERE provider = ? AND external_id = ?', provider, externalId)
|
|
238
|
+
.toArray()[0] !== undefined;
|
|
239
|
+
if (existed)
|
|
240
|
+
return false;
|
|
241
|
+
this.sql.exec(`INSERT OR IGNORE INTO _substrat_identities
|
|
242
|
+
(provider, external_id, principal_id, tenant_id, scope_id, created_at)
|
|
243
|
+
VALUES (?, ?, ?, ?, ?, ?)`, provider, externalId, principal, tenantId, scopeId, createdAt);
|
|
244
|
+
return true;
|
|
245
|
+
}
|
|
246
|
+
resolveIdentity(provider, externalId) {
|
|
247
|
+
const row = this.sql
|
|
248
|
+
.exec(`SELECT principal_id, tenant_id, scope_id FROM _substrat_identities
|
|
249
|
+
WHERE provider = ? AND external_id = ?`, provider, externalId)
|
|
250
|
+
.toArray()[0];
|
|
251
|
+
if (!row)
|
|
252
|
+
return undefined;
|
|
253
|
+
return { principal: row.principal_id, tenantId: row.tenant_id, scopeId: row.scope_id };
|
|
254
|
+
}
|
|
255
|
+
// -- admin audit log (control-plane.md §4.4) --------------------------------
|
|
256
|
+
/** Append one audit row. before/after are arbitrary JSON, stringified here. */
|
|
257
|
+
recordAdmin(entry) {
|
|
258
|
+
this.sql.exec(`INSERT INTO _substrat_admin_log
|
|
259
|
+
(id, actor, action, tenant_id, scope_id, vertical, before, after, at)
|
|
260
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, entry.id, entry.actor, entry.action, entry.tenantId, entry.scopeId, entry.vertical, entry.before == null ? null : JSON.stringify(entry.before), entry.after == null ? null : JSON.stringify(entry.after), entry.at);
|
|
261
|
+
}
|
|
262
|
+
auditLog(tenantId) {
|
|
263
|
+
const rows = (tenantId
|
|
264
|
+
? this.sql.exec('SELECT * FROM _substrat_admin_log WHERE tenant_id = ? ORDER BY id', tenantId)
|
|
265
|
+
: this.sql.exec('SELECT * FROM _substrat_admin_log ORDER BY id')).toArray();
|
|
266
|
+
return rows.map((r) => ({
|
|
267
|
+
id: r.id,
|
|
268
|
+
actor: r.actor,
|
|
269
|
+
action: r.action,
|
|
270
|
+
tenantId: r.tenant_id,
|
|
271
|
+
scopeId: r.scope_id,
|
|
272
|
+
vertical: r.vertical,
|
|
273
|
+
before: r.before === null ? null : JSON.parse(r.before),
|
|
274
|
+
after: r.after === null ? null : JSON.parse(r.after),
|
|
275
|
+
at: r.at,
|
|
276
|
+
}));
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
//# sourceMappingURL=control-plane-do.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"control-plane-do.js","sourceRoot":"","sources":["../src/control-plane-do.ts"],"names":[],"mappings":"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"}
|
package/dist/host.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type PlatformActorId, type PrincipalId, type ScopeId, type TenantId } from '@substrat-run/contracts';
|
|
2
|
+
import { type HostAdmin, type ModuleRegistration, type OperationHandler, type PermissionChecker, type ProvisionScopeInput, type ScopeHost, type ScopeStub } from '@substrat-run/kernel';
|
|
3
|
+
export interface CloudflareScopeHostOptions {
|
|
4
|
+
scope: DurableObjectNamespace;
|
|
5
|
+
controlPlane: DurableObjectNamespace;
|
|
6
|
+
/**
|
|
7
|
+
* Accepted for parity with the pure adapter's constructor. In milestone 1 the
|
|
8
|
+
* ScopeDO owns permission evaluation (a checker function cannot cross the RPC
|
|
9
|
+
* boundary), so this is informational only — the DO builds the tuple checker.
|
|
10
|
+
*/
|
|
11
|
+
checker?: PermissionChecker;
|
|
12
|
+
}
|
|
13
|
+
export declare class CloudflareScopeHost implements ScopeHost {
|
|
14
|
+
readonly admin: HostAdmin;
|
|
15
|
+
private readonly scopeNs;
|
|
16
|
+
private readonly cp;
|
|
17
|
+
private readonly moduleIds;
|
|
18
|
+
private readonly operations;
|
|
19
|
+
private readonly predicateNames;
|
|
20
|
+
private readonly withdrawn;
|
|
21
|
+
private readonly operationEntitlement;
|
|
22
|
+
constructor(options: CloudflareScopeHostOptions);
|
|
23
|
+
registerModule(registration: ModuleRegistration): void;
|
|
24
|
+
defineOperation<I, O>(name: string, _handler: OperationHandler<I, O>): void;
|
|
25
|
+
private bindOperation;
|
|
26
|
+
provisionScope(actor: PlatformActorId, input: ProvisionScopeInput): Promise<void>;
|
|
27
|
+
getScope(principal: PrincipalId, tenantId: TenantId, scopeId: ScopeId): Promise<ScopeStub>;
|
|
28
|
+
close(): Promise<void>;
|
|
29
|
+
private buildAdmin;
|
|
30
|
+
private recordAdmin;
|
|
31
|
+
private writeScopeTuple;
|
|
32
|
+
private scopeStub;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=host.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"AAAA,OAAO,EAgBL,KAAK,eAAe,EACpB,KAAK,WAAW,EAIhB,KAAK,OAAO,EAGZ,KAAK,QAAQ,EAEd,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,sBAAsB,CAAC;AA2G9B,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE,sBAAsB,CAAC;IAC9B,YAAY,EAAE,sBAAsB,CAAC;IACrC;;;;OAIG;IACH,OAAO,CAAC,EAAE,iBAAiB,CAAC;CAC7B;AAED,qBAAa,mBAAoB,YAAW,SAAS;IACnD,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAE1B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;IACjD,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAmB;IAItC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqB;IAC/C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAqB;IAChD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA6B;IAC5D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA6B;IACvD,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAA6B;gBAEtD,OAAO,EAAE,0BAA0B;IAU/C,cAAc,CAAC,YAAY,EAAE,kBAAkB,GAAG,IAAI;IAgDtD,eAAe,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI;IAI3E,OAAO,CAAC,aAAa;IAQf,cAAc,CAAC,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAwBjF,QAAQ,CACZ,SAAS,EAAE,WAAW,EACtB,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,SAAS,CAAC;IA6Bf,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAM5B,OAAO,CAAC,UAAU;YAmMJ,WAAW;YAoBX,eAAe;IAU7B,OAAO,CAAC,SAAS;CAKlB"}
|