@substrat-run/adapter-sqlite 0.1.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/README.md +49 -0
- package/dist/actor.d.ts +11 -0
- package/dist/actor.d.ts.map +1 -0
- package/dist/actor.js +16 -0
- package/dist/actor.js.map +1 -0
- package/dist/checker.d.ts +11 -0
- package/dist/checker.d.ts.map +1 -0
- package/dist/checker.js +136 -0
- package/dist/checker.js.map +1 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +431 -0
- package/dist/index.js.map +1 -0
- package/package.json +43 -0
package/README.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# @substrat-run/adapter-sqlite
|
|
2
|
+
|
|
3
|
+
Pure-SQLite scope host for [Substrat](https://github.com/substrat-run/substrat) — real
|
|
4
|
+
kernel semantics with **no Cloudflare dependency**.
|
|
5
|
+
|
|
6
|
+
One SQLite file per scope, a per-scope actor for strict serialization, a directory
|
|
7
|
+
database for fail-closed scope addressing, and a kernel-stamped event outbox. It is not
|
|
8
|
+
a mock: it is the adapter that local development and CI run on, and the reason the
|
|
9
|
+
self-host/escrow story is literally true (single-node, but runnable).
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { SqliteScopeHost } from '@substrat-run/adapter-sqlite';
|
|
15
|
+
import { UNSAFE_allowAllChecker } from '@substrat-run/kernel';
|
|
16
|
+
|
|
17
|
+
const host = new SqliteScopeHost({
|
|
18
|
+
dir: './data', // one .sqlite file per scope + _directory.sqlite
|
|
19
|
+
checker: UNSAFE_allowAllChecker, // omit for the secure default: deny everything
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
await host.provisionScope({ tenantId, scopeId, jurisdiction: 'eu' }); // idempotent
|
|
23
|
+
const stub = await host.getScope(principal, tenantId, scopeId);
|
|
24
|
+
await stub.invoke('workorder/create', input);
|
|
25
|
+
await host.close();
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Guarantees
|
|
29
|
+
|
|
30
|
+
This adapter passes the full
|
|
31
|
+
[`@substrat-run/contract-tests`](https://npmjs.com/package/@substrat-run/contract-tests) suite —
|
|
32
|
+
the same suite the Cloudflare adapter (Durable Objects) must pass unchanged:
|
|
33
|
+
|
|
34
|
+
- strict per-scope serialization (concurrent read-modify-writes cannot interleave)
|
|
35
|
+
- structured-clone boundary on every stub call, both directions
|
|
36
|
+
- kernel-stamped event envelopes; PII-classed events without a `subjectId` are rejected
|
|
37
|
+
- scope storage isolation; mismatched `(tenantId, scopeId)` pairs fail closed
|
|
38
|
+
|
|
39
|
+
## Notes
|
|
40
|
+
|
|
41
|
+
- Uses [better-sqlite3](https://npmjs.com/package/better-sqlite3) (native module). With
|
|
42
|
+
pnpm 10+, allow its build script via `pnpm.onlyBuiltDependencies`.
|
|
43
|
+
- Scope databases run in WAL mode and can be opened read-only with any SQLite tool —
|
|
44
|
+
local debugging is just opening a file.
|
|
45
|
+
|
|
46
|
+
## Status
|
|
47
|
+
|
|
48
|
+
Pre-release (0.x). Migration journal, attachments, and the outbox drain are still
|
|
49
|
+
landing.
|
package/dist/actor.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-scope actor: strict serialization (K-6). One operation runs to
|
|
3
|
+
* completion before the next starts — the conservative semantics both
|
|
4
|
+
* adapters can honor (the DO over-delivers via input gates; we deliver
|
|
5
|
+
* exactly this).
|
|
6
|
+
*/
|
|
7
|
+
export declare class ScopeActor {
|
|
8
|
+
private tail;
|
|
9
|
+
enqueue<T>(op: () => Promise<T> | T): Promise<T>;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=actor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actor.d.ts","sourceRoot":"","sources":["../src/actor.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,IAAI,CAAuC;IAEnD,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;CAMjD"}
|
package/dist/actor.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-scope actor: strict serialization (K-6). One operation runs to
|
|
3
|
+
* completion before the next starts — the conservative semantics both
|
|
4
|
+
* adapters can honor (the DO over-delivers via input gates; we deliver
|
|
5
|
+
* exactly this).
|
|
6
|
+
*/
|
|
7
|
+
export class ScopeActor {
|
|
8
|
+
tail = Promise.resolve();
|
|
9
|
+
enqueue(op) {
|
|
10
|
+
const result = this.tail.then(op);
|
|
11
|
+
// The chain must survive failures; callers still see the rejection.
|
|
12
|
+
this.tail = result.catch(() => undefined);
|
|
13
|
+
return result;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=actor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actor.js","sourceRoot":"","sources":["../src/actor.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,OAAO,UAAU;IACb,IAAI,GAAqB,OAAO,CAAC,OAAO,EAAE,CAAC;IAEnD,OAAO,CAAI,EAAwB;QACjC,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAClC,oEAAoE;QACpE,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC1C,OAAO,MAAM,CAAC;IAChB,CAAC;CACF"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type Database from 'better-sqlite3';
|
|
2
|
+
import { type RoleDefinition } from '@substrat-run/contracts';
|
|
3
|
+
import type { PermissionChecker } from '@substrat-run/kernel';
|
|
4
|
+
export interface CheckerDeps {
|
|
5
|
+
directory: Database.Database;
|
|
6
|
+
/** Resolve an OPEN scope db; checks only run inside operations, so it is open. */
|
|
7
|
+
scopeDb(scopeId: string): Database.Database | undefined;
|
|
8
|
+
getRole(tenantId: string, key: string): RoleDefinition | undefined;
|
|
9
|
+
}
|
|
10
|
+
export declare function createTupleChecker(deps: CheckerDeps): PermissionChecker;
|
|
11
|
+
//# sourceMappingURL=checker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checker.d.ts","sourceRoot":"","sources":["../src/checker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAQL,KAAK,cAAc,EACpB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAiB9D,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,QAAQ,CAAC,QAAQ,CAAC;IAC7B,kFAAkF;IAClF,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ,CAAC,QAAQ,GAAG,SAAS,CAAC;IACxD,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAAC;CACpE;AAeD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,WAAW,GAAG,iBAAiB,CAmJvE"}
|
package/dist/checker.js
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { objectRef, } from '@substrat-run/contracts';
|
|
2
|
+
/**
|
|
3
|
+
* The built-in constrained relationship-tuple evaluator (design doc §4.2,
|
|
4
|
+
* plan D-23). Fixed four-rule algebra — role expansion, tenancy-tree
|
|
5
|
+
* inheritance, declared entity parent edges (depth ≤ 4), membership — no
|
|
6
|
+
* negation, no configurable rewrites. Every allow carries its tuple proof.
|
|
7
|
+
*
|
|
8
|
+
* Tuple placement: scope-level and entity tuples live in the scope database
|
|
9
|
+
* (`_substrat_tuples`); tenant-level assignments/grants and org membership
|
|
10
|
+
* live in the directory (`_substrat_tenant_tuples`). Everything is evaluated
|
|
11
|
+
* inside the caller's serialization domain, so check-after-write consistency
|
|
12
|
+
* is free — the "no zookies" property.
|
|
13
|
+
*/
|
|
14
|
+
const ENTITY_WALK_DEPTH = 4;
|
|
15
|
+
const t = (subject, relation, object) => ({
|
|
16
|
+
subject: objectRef.parse(subject),
|
|
17
|
+
relation,
|
|
18
|
+
object: objectRef.parse(object),
|
|
19
|
+
});
|
|
20
|
+
export function createTupleChecker(deps) {
|
|
21
|
+
const tenantTuples = (tenantId, subject, relationPrefix) => deps.directory
|
|
22
|
+
.prepare(`SELECT subject, relation, object, expires_at FROM _substrat_tenant_tuples
|
|
23
|
+
WHERE tenant_id = ? AND subject = ? AND relation LIKE ?`)
|
|
24
|
+
.all(tenantId, subject, `${relationPrefix}%`);
|
|
25
|
+
const scopeTuples = (db, subject, relationPrefix) => db
|
|
26
|
+
.prepare(`SELECT subject, relation, object, expires_at FROM _substrat_tuples
|
|
27
|
+
WHERE subject = ? AND relation LIKE ?`)
|
|
28
|
+
.all(subject, `${relationPrefix}%`);
|
|
29
|
+
const live = (row, now) => row.expires_at === null || row.expires_at > now;
|
|
30
|
+
return {
|
|
31
|
+
async check(principal, permission, node, entity) {
|
|
32
|
+
const now = new Date().toISOString();
|
|
33
|
+
const deny = { allowed: false, checked: permission, node };
|
|
34
|
+
const scopeDb = node.scopeId ? deps.scopeDb(node.scopeId) : undefined;
|
|
35
|
+
// Rule 4 — membership: the subject set is the principal plus its orgs.
|
|
36
|
+
const subjects = [
|
|
37
|
+
{ ref: `principal:${principal}` },
|
|
38
|
+
];
|
|
39
|
+
for (const m of tenantTuples(node.tenantId, `principal:${principal}`, 'member')) {
|
|
40
|
+
if (m.relation === 'member' && live(m, now)) {
|
|
41
|
+
subjects.push({ ref: m.object, via: t(m.subject, m.relation, m.object) });
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
// Inheritance (rule 2): a scope check also consults tenant-level tuples.
|
|
45
|
+
const nodeObjects = node.scopeId
|
|
46
|
+
? [
|
|
47
|
+
{ obj: `scope:${node.scopeId}`, scoped: true },
|
|
48
|
+
{ obj: `tenant:${node.tenantId}`, scoped: false },
|
|
49
|
+
]
|
|
50
|
+
: [{ obj: `tenant:${node.tenantId}`, scoped: false }];
|
|
51
|
+
const tuplesFor = (subject, prefix, scoped) => scoped
|
|
52
|
+
? scopeDb
|
|
53
|
+
? scopeTuples(scopeDb, subject, prefix)
|
|
54
|
+
: []
|
|
55
|
+
: tenantTuples(node.tenantId, subject, prefix);
|
|
56
|
+
for (const nodeObj of nodeObjects) {
|
|
57
|
+
for (const subject of subjects) {
|
|
58
|
+
// Rule 1 — role expansion.
|
|
59
|
+
for (const row of tuplesFor(subject.ref, 'role:', nodeObj.scoped)) {
|
|
60
|
+
if (row.object !== nodeObj.obj || !live(row, now))
|
|
61
|
+
continue;
|
|
62
|
+
const roleKey = row.relation.slice('role:'.length);
|
|
63
|
+
const role = deps.getRole(node.tenantId, roleKey);
|
|
64
|
+
if (role?.permissions.includes(permission)) {
|
|
65
|
+
return {
|
|
66
|
+
allowed: true,
|
|
67
|
+
proof: [
|
|
68
|
+
...(subject.via ? [subject.via] : []),
|
|
69
|
+
t(row.subject, row.relation, row.object),
|
|
70
|
+
t(`role:${roleKey}`, `granted:${permission}`, nodeObj.obj),
|
|
71
|
+
],
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// Direct grants at the node.
|
|
76
|
+
for (const row of tuplesFor(subject.ref, `granted:${permission}`, nodeObj.scoped)) {
|
|
77
|
+
if (row.object === nodeObj.obj && row.relation === `granted:${permission}` && live(row, now)) {
|
|
78
|
+
return {
|
|
79
|
+
allowed: true,
|
|
80
|
+
proof: [
|
|
81
|
+
...(subject.via ? [subject.via] : []),
|
|
82
|
+
t(row.subject, row.relation, row.object),
|
|
83
|
+
],
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// Rule 3 — entity walk along declared parent edges (entity grants are
|
|
90
|
+
// scope-local by construction).
|
|
91
|
+
if (entity && scopeDb) {
|
|
92
|
+
let frontier = [
|
|
93
|
+
{ ref: `${entity.entityType}:${entity.entityId}`, chain: [] },
|
|
94
|
+
];
|
|
95
|
+
for (let depth = 0; depth <= ENTITY_WALK_DEPTH && frontier.length > 0; depth++) {
|
|
96
|
+
// grant lookup at current frontier objects
|
|
97
|
+
for (const candidate of frontier) {
|
|
98
|
+
for (const subject of subjects) {
|
|
99
|
+
const grant = scopeDb
|
|
100
|
+
.prepare(`SELECT subject, relation, object, expires_at FROM _substrat_tuples
|
|
101
|
+
WHERE subject = ? AND relation = ? AND object = ?`)
|
|
102
|
+
.get(subject.ref, `granted:${permission}`, candidate.ref);
|
|
103
|
+
if (grant && live(grant, now)) {
|
|
104
|
+
return {
|
|
105
|
+
allowed: true,
|
|
106
|
+
proof: [
|
|
107
|
+
...(subject.via ? [subject.via] : []),
|
|
108
|
+
...candidate.chain,
|
|
109
|
+
t(grant.subject, grant.relation, grant.object),
|
|
110
|
+
],
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// expand one level of parents
|
|
116
|
+
const next = [];
|
|
117
|
+
for (const candidate of frontier) {
|
|
118
|
+
const parents = scopeDb
|
|
119
|
+
.prepare(`SELECT subject, relation, object, expires_at FROM _substrat_tuples
|
|
120
|
+
WHERE subject = ? AND relation = 'parent'`)
|
|
121
|
+
.all(candidate.ref);
|
|
122
|
+
for (const p of parents) {
|
|
123
|
+
next.push({
|
|
124
|
+
ref: p.object,
|
|
125
|
+
chain: [...candidate.chain, t(p.subject, 'parent', p.object)],
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
frontier = next;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return deny;
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=checker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checker.js","sourceRoot":"","sources":["../src/checker.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { 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 SqliteScopeHostOptions {
|
|
4
|
+
/** Directory holding one SQLite file per scope plus the directory database. */
|
|
5
|
+
dir: string;
|
|
6
|
+
/** Defaults to the built-in tuple checker (deny-by-default on empty tuples). */
|
|
7
|
+
checker?: PermissionChecker;
|
|
8
|
+
}
|
|
9
|
+
export declare class SqliteScopeHost implements ScopeHost {
|
|
10
|
+
readonly admin: HostAdmin;
|
|
11
|
+
private readonly dir;
|
|
12
|
+
private readonly checker;
|
|
13
|
+
private readonly directory;
|
|
14
|
+
private readonly scopes;
|
|
15
|
+
private readonly scopesById;
|
|
16
|
+
private readonly operations;
|
|
17
|
+
private readonly modules;
|
|
18
|
+
private readonly relations;
|
|
19
|
+
private readonly roles;
|
|
20
|
+
private readonly systemPrincipal;
|
|
21
|
+
constructor(options: SqliteScopeHostOptions);
|
|
22
|
+
registerModule(registration: ModuleRegistration): void;
|
|
23
|
+
defineOperation<I, O>(name: string, handler: OperationHandler<I, O>): void;
|
|
24
|
+
provisionScope(input: ProvisionScopeInput): Promise<void>;
|
|
25
|
+
getScope(principal: PrincipalId, tenantId: TenantId, scopeId: ScopeId): Promise<ScopeStub>;
|
|
26
|
+
close(): Promise<void>;
|
|
27
|
+
private dispatch;
|
|
28
|
+
private parseOutboxRow;
|
|
29
|
+
private buildAdmin;
|
|
30
|
+
private loadRoles;
|
|
31
|
+
private operationContext;
|
|
32
|
+
private applyPendingMigrations;
|
|
33
|
+
private runtime;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAeL,KAAK,WAAW,EAGhB,KAAK,OAAO,EACZ,KAAK,QAAQ,EACd,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAGL,KAAK,SAAS,EACd,KAAK,kBAAkB,EAEvB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EAExB,KAAK,SAAS,EACd,KAAK,SAAS,EAGf,MAAM,sBAAsB,CAAC;AAkB9B,MAAM,WAAW,sBAAsB;IACrC,+EAA+E;IAC/E,GAAG,EAAE,MAAM,CAAC;IACZ,gFAAgF;IAChF,OAAO,CAAC,EAAE,iBAAiB,CAAC;CAC7B;AAuDD,qBAAa,eAAgB,YAAW,SAAS;IAC/C,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoB;IAC5C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoB;IAC9C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmC;IAC1D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAmC;IAC9D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAuD;IAClF,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuC;IAC/D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAkC;IAC5D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqC;IAC3D,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA0C;gBAE9D,OAAO,EAAE,sBAAsB;IA0C3C,cAAc,CAAC,YAAY,EAAE,kBAAkB,GAAG,IAAI;IAmCtD,eAAe,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI;IAKpE,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBzD,QAAQ,CACZ,SAAS,EAAE,WAAW,EACtB,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,SAAS,CAAC;IAsCf,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YAYd,QAAQ;IAkDtB,OAAO,CAAC,cAAc;IAoBtB,OAAO,CAAC,UAAU;IA4GlB,OAAO,CAAC,SAAS;IAejB,OAAO,CAAC,gBAAgB;IA6ExB,OAAO,CAAC,sBAAsB;IAuC9B,OAAO,CAAC,OAAO;CAoBhB"}
|