@xyo-network/event-kit-statement-graph 0.0.1
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 +59 -0
- package/dist/neutral/grantReadModel.d.ts +21 -0
- package/dist/neutral/grantReadModel.d.ts.map +1 -0
- package/dist/neutral/index.d.ts +3 -0
- package/dist/neutral/index.d.ts.map +1 -0
- package/dist/neutral/index.mjs +48 -0
- package/dist/neutral/index.mjs.map +7 -0
- package/package.json +78 -0
package/README.md
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# `@xyo-network/event-kit-statement-graph`
|
|
2
|
+
|
|
3
|
+
Read-model adapter between the canonical XL1 Statement Graph viewer and the
|
|
4
|
+
Event Kit wake-grant authorizer.
|
|
5
|
+
|
|
6
|
+
```ts
|
|
7
|
+
const readModel = createStatementGraphGrantReadModel({ viewer })
|
|
8
|
+
const grants = createStatementGraphWakeGrantAuthorizer({ viewer: readModel })
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
`viewer` is any `StatementGraphViewer` — a `StateStatementGraphViewer` over
|
|
12
|
+
engine state, a replay controller's viewer, or another backing.
|
|
13
|
+
|
|
14
|
+
## What this package does and does not do
|
|
15
|
+
|
|
16
|
+
It is a translation seam only. It narrows the canonical branded source/hash
|
|
17
|
+
types, preserves every field the authorizer needs as grant evidence, and drops
|
|
18
|
+
nothing. It makes no authorization decision and applies no freshness policy.
|
|
19
|
+
|
|
20
|
+
Under Statement Graph v2 the protocol owns **claim only**: there is no `target`
|
|
21
|
+
and no revoke verb, so the grant body names its own `publisher` and negation is
|
|
22
|
+
an Event Kit revocation object claimed by the pinned controller. See
|
|
23
|
+
[D-003](../../docs/decisions/D-003-STATEMENT-GRAPH-V2-GRANTS.md).
|
|
24
|
+
|
|
25
|
+
Addresses and hashes are **parsed**, not cast. A malformed address therefore
|
|
26
|
+
reaches the caller as `grant-unavailable` rather than silently querying a
|
|
27
|
+
nonsense key and reading as "no grant".
|
|
28
|
+
|
|
29
|
+
## Evidence
|
|
30
|
+
|
|
31
|
+
Specs fold a `FakeStatementChain` through the real engine —
|
|
32
|
+
`applyStatementTransaction` over decoded blocks and verified bodies — and drive
|
|
33
|
+
`admitAndEnqueue` against the resulting viewer. Exact-scope claims admit; a
|
|
34
|
+
wrong controller, a differently scoped or unscoped route, a missing `enqueue`
|
|
35
|
+
permission, and a revoke all reject; a lagging view rejects as stale and an
|
|
36
|
+
ahead-of-finality view rejects rather than being trusted.
|
|
37
|
+
|
|
38
|
+
A never-folded read model carries watermark `-1` and fails closed as
|
|
39
|
+
`grant-unavailable`, keeping "the view is not ready" distinguishable from "the
|
|
40
|
+
controller granted nothing".
|
|
41
|
+
|
|
42
|
+
Live specs under `src/spec/api-local/` run the same fold against a **real local
|
|
43
|
+
XL1 chain**: a Claim transaction published with the statement-graph SDK,
|
|
44
|
+
confirmed and finalized, then folded from real finalized blocks into an
|
|
45
|
+
admission decision whose evidence cites the on-chain claim at its real height.
|
|
46
|
+
The gateway viewer satisfies `FinalizedBlockViewer` structurally, so the fold
|
|
47
|
+
code is identical across both substrates. Run with
|
|
48
|
+
`pnpm test:api-local-statements` — publishing specs need their own chain, since
|
|
49
|
+
the dev chain stops producing blocks after one statement transaction.
|
|
50
|
+
|
|
51
|
+
The full lifecycle runs live: a grant admits, a negation in a **later** finalized
|
|
52
|
+
transaction disables, and a later redundant claim leaves the asserted height
|
|
53
|
+
frozen while only the liveness clock advances. Same-block negation is covered too
|
|
54
|
+
via v2's `hashes[]` fan-out, where a grant and the revocation naming it ride one
|
|
55
|
+
transaction and the publisher is born disabled.
|
|
56
|
+
|
|
57
|
+
Bodies are served from an in-process datalake; the chain carries commitments, not
|
|
58
|
+
bodies. Scope-mismatch and wrong-controller vectors stay on the deterministic
|
|
59
|
+
chain.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { StatementGraphGrantReadModel } from '@xyo-network/event-kit-protocol';
|
|
2
|
+
import type { StatementGraphViewer } from '@xyo-network/xl1-statement-graph-engine';
|
|
3
|
+
export interface StatementGraphGrantReadModelOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Canonical Statement Graph read surface — a `StateStatementGraphViewer` over
|
|
6
|
+
* engine state, a replay controller's viewer, or any other backing.
|
|
7
|
+
*/
|
|
8
|
+
readonly viewer: StatementGraphViewer;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Adapts the canonical Statement Graph v2 viewer to the unbranded read model
|
|
12
|
+
* the Event Kit grant authorizer consumes.
|
|
13
|
+
*
|
|
14
|
+
* This is a translation seam only. It narrows branded query and record types
|
|
15
|
+
* and preserves every field the authorizer needs as grant evidence; it makes no
|
|
16
|
+
* authorization decision, applies no freshness policy, and drops no claim.
|
|
17
|
+
* Statement Graph remains the sole owner of claim semantics — and under v2 that
|
|
18
|
+
* is the whole lifecycle, since there is no revoke verb to own.
|
|
19
|
+
*/
|
|
20
|
+
export declare function createStatementGraphGrantReadModel(options: StatementGraphGrantReadModelOptions): StatementGraphGrantReadModel;
|
|
21
|
+
//# sourceMappingURL=grantReadModel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grantReadModel.d.ts","sourceRoot":"","sources":["../../src/grantReadModel.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAIV,4BAA4B,EAC7B,MAAM,iCAAiC,CAAA;AAExC,OAAO,KAAK,EAEV,oBAAoB,EACrB,MAAM,yCAAyC,CAAA;AAGhD,MAAM,WAAW,mCAAmC;IAClD;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAA;CACtC;AAED;;;;;;;;;GASG;AACH,wBAAgB,kCAAkC,CAChD,OAAO,EAAE,mCAAmC,GAC3C,4BAA4B,CAqB9B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,mCAAmC,EAAE,MAAM,qBAAqB,CAAA;AAC9E,OAAO,EAAE,kCAAkC,EAAE,MAAM,qBAAqB,CAAA"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// src/grantReadModel.ts
|
|
2
|
+
import { HashZod } from "@ariestools/sdk";
|
|
3
|
+
import { XyoAddressZod } from "@xyo-network/sdk-protocol/address";
|
|
4
|
+
function createStatementGraphGrantReadModel(options) {
|
|
5
|
+
const { viewer } = options;
|
|
6
|
+
return Object.freeze({
|
|
7
|
+
async head() {
|
|
8
|
+
return await viewer.head();
|
|
9
|
+
},
|
|
10
|
+
async claims(source, query) {
|
|
11
|
+
const records = await viewer.claims(XyoAddressZod.parse(source), toClaimQuery(query));
|
|
12
|
+
return Object.freeze(records.map(toGrantClaim));
|
|
13
|
+
},
|
|
14
|
+
async object(objectHash) {
|
|
15
|
+
const record = await viewer.object(HashZod.parse(objectHash));
|
|
16
|
+
return record === void 0 ? void 0 : toGrantObject(record);
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
function toClaimQuery(query) {
|
|
21
|
+
if (query === void 0) return void 0;
|
|
22
|
+
return {
|
|
23
|
+
...query.declaredObjectSchemaPrefix === void 0 ? {} : { declaredObjectSchemaPrefix: query.declaredObjectSchemaPrefix },
|
|
24
|
+
...query.objectHash === void 0 ? {} : { objectHash: HashZod.parse(query.objectHash) }
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function toGrantClaim(record) {
|
|
28
|
+
return Object.freeze({
|
|
29
|
+
declaredObjectSchema: record.declaredObjectSchema,
|
|
30
|
+
firstBlock: record.firstBlock,
|
|
31
|
+
firstEventHash: record.firstEventHash,
|
|
32
|
+
lastBlock: record.lastBlock,
|
|
33
|
+
objectHash: record.objectHash,
|
|
34
|
+
source: record.source
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
function toGrantObject(record) {
|
|
38
|
+
return Object.freeze({
|
|
39
|
+
assurance: record.assurance,
|
|
40
|
+
declaredSchema: record.declaredSchema,
|
|
41
|
+
objectHash: record.objectHash,
|
|
42
|
+
params: record.params === null ? null : Object.freeze({ ...record.params })
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
export {
|
|
46
|
+
createStatementGraphGrantReadModel
|
|
47
|
+
};
|
|
48
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/grantReadModel.ts"],
|
|
4
|
+
"sourcesContent": ["import { HashZod } from '@ariestools/sdk'\nimport type {\n StatementGrantClaim,\n StatementGrantClaimQuery,\n StatementGrantObject,\n StatementGraphGrantReadModel,\n} from '@xyo-network/event-kit-protocol'\nimport { XyoAddressZod } from '@xyo-network/sdk-protocol/address'\nimport type {\n ClaimQuery,\n StatementGraphViewer,\n} from '@xyo-network/xl1-statement-graph-engine'\nimport type { ClaimRecord, ObjectRecord } from '@xyo-network/xl1-statement-graph-schemas'\n\nexport interface StatementGraphGrantReadModelOptions {\n /**\n * Canonical Statement Graph read surface \u2014 a `StateStatementGraphViewer` over\n * engine state, a replay controller's viewer, or any other backing.\n */\n readonly viewer: StatementGraphViewer\n}\n\n/**\n * Adapts the canonical Statement Graph v2 viewer to the unbranded read model\n * the Event Kit grant authorizer consumes.\n *\n * This is a translation seam only. It narrows branded query and record types\n * and preserves every field the authorizer needs as grant evidence; it makes no\n * authorization decision, applies no freshness policy, and drops no claim.\n * Statement Graph remains the sole owner of claim semantics \u2014 and under v2 that\n * is the whole lifecycle, since there is no revoke verb to own.\n */\nexport function createStatementGraphGrantReadModel(\n options: StatementGraphGrantReadModelOptions,\n): StatementGraphGrantReadModel {\n const { viewer } = options\n\n return Object.freeze({\n async head(): Promise<number> {\n return await viewer.head()\n },\n\n async claims(\n source: string,\n query?: StatementGrantClaimQuery,\n ): Promise<readonly StatementGrantClaim[]> {\n const records = await viewer.claims(XyoAddressZod.parse(source), toClaimQuery(query))\n return Object.freeze(records.map(toGrantClaim))\n },\n\n async object(objectHash: string): Promise<StatementGrantObject | undefined> {\n const record = await viewer.object(HashZod.parse(objectHash))\n return record === undefined ? undefined : toGrantObject(record)\n },\n })\n}\n\n/**\n * Rebrands the query fields. Parsing rather than casting means a malformed hash\n * reaches the viewer as a throw \u2014 surfacing as `grant-unavailable` \u2014 instead of\n * silently querying a nonsense key and reading as \"no grant\".\n */\nfunction toClaimQuery(query?: StatementGrantClaimQuery): ClaimQuery | undefined {\n if (query === undefined) return undefined\n return {\n ...(query.declaredObjectSchemaPrefix === undefined\n ? {}\n : { declaredObjectSchemaPrefix: query.declaredObjectSchemaPrefix }),\n ...(query.objectHash === undefined ? {} : { objectHash: HashZod.parse(query.objectHash) }),\n }\n}\n\n/**\n * `firstEventHash` identifies the materializing claim, so the authorizer can\n * cite one concrete transition as evidence rather than a bare boolean. A\n * redundant claim moves only `lastBlock`, so evidence cannot be backdated or\n * refreshed by re-claiming.\n */\nfunction toGrantClaim(record: ClaimRecord): StatementGrantClaim {\n return Object.freeze({\n declaredObjectSchema: record.declaredObjectSchema,\n firstBlock: record.firstBlock,\n firstEventHash: record.firstEventHash,\n lastBlock: record.lastBlock,\n objectHash: record.objectHash,\n source: record.source,\n })\n}\n\nfunction toGrantObject(record: ObjectRecord): StatementGrantObject {\n return Object.freeze({\n assurance: record.assurance,\n declaredSchema: record.declaredSchema,\n objectHash: record.objectHash,\n params: record.params === null ? null : Object.freeze({ ...record.params }),\n })\n}\n"],
|
|
5
|
+
"mappings": ";AAAA,SAAS,eAAe;AAOxB,SAAS,qBAAqB;AAyBvB,SAAS,mCACd,SAC8B;AAC9B,QAAM,EAAE,OAAO,IAAI;AAEnB,SAAO,OAAO,OAAO;AAAA,IACnB,MAAM,OAAwB;AAC5B,aAAO,MAAM,OAAO,KAAK;AAAA,IAC3B;AAAA,IAEA,MAAM,OACJ,QACA,OACyC;AACzC,YAAM,UAAU,MAAM,OAAO,OAAO,cAAc,MAAM,MAAM,GAAG,aAAa,KAAK,CAAC;AACpF,aAAO,OAAO,OAAO,QAAQ,IAAI,YAAY,CAAC;AAAA,IAChD;AAAA,IAEA,MAAM,OAAO,YAA+D;AAC1E,YAAM,SAAS,MAAM,OAAO,OAAO,QAAQ,MAAM,UAAU,CAAC;AAC5D,aAAO,WAAW,SAAY,SAAY,cAAc,MAAM;AAAA,IAChE;AAAA,EACF,CAAC;AACH;AAOA,SAAS,aAAa,OAA0D;AAC9E,MAAI,UAAU,OAAW,QAAO;AAChC,SAAO;AAAA,IACL,GAAI,MAAM,+BAA+B,SACrC,CAAC,IACD,EAAE,4BAA4B,MAAM,2BAA2B;AAAA,IACnE,GAAI,MAAM,eAAe,SAAY,CAAC,IAAI,EAAE,YAAY,QAAQ,MAAM,MAAM,UAAU,EAAE;AAAA,EAC1F;AACF;AAQA,SAAS,aAAa,QAA0C;AAC9D,SAAO,OAAO,OAAO;AAAA,IACnB,sBAAsB,OAAO;AAAA,IAC7B,YAAY,OAAO;AAAA,IACnB,gBAAgB,OAAO;AAAA,IACvB,WAAW,OAAO;AAAA,IAClB,YAAY,OAAO;AAAA,IACnB,QAAQ,OAAO;AAAA,EACjB,CAAC;AACH;AAEA,SAAS,cAAc,QAA4C;AACjE,SAAO,OAAO,OAAO;AAAA,IACnB,WAAW,OAAO;AAAA,IAClB,gBAAgB,OAAO;AAAA,IACvB,YAAY,OAAO;AAAA,IACnB,QAAQ,OAAO,WAAW,OAAO,OAAO,OAAO,OAAO,EAAE,GAAG,OAAO,OAAO,CAAC;AAAA,EAC5E,CAAC;AACH;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@xyo-network/event-kit-statement-graph",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Statement Graph read-model adapter for Event Kit wake grants",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"xyo",
|
|
7
|
+
"xl1",
|
|
8
|
+
"event-kit",
|
|
9
|
+
"statement-graph",
|
|
10
|
+
"typescript"
|
|
11
|
+
],
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/XYOracleNetwork/event-kit/issues"
|
|
14
|
+
},
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/XYOracleNetwork/event-kit.git",
|
|
18
|
+
"directory": "packages/statement-graph"
|
|
19
|
+
},
|
|
20
|
+
"license": "UNLICENSED",
|
|
21
|
+
"sideEffects": false,
|
|
22
|
+
"type": "module",
|
|
23
|
+
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"types": "./dist/neutral/index.d.ts",
|
|
26
|
+
"default": "./dist/neutral/index.mjs"
|
|
27
|
+
},
|
|
28
|
+
"./package.json": "./package.json",
|
|
29
|
+
"./README.md": "./README.md"
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"dist",
|
|
33
|
+
"README.md"
|
|
34
|
+
],
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@xyo-network/event-kit-protocol": "~0.0.1"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@ariestools/lib-neutral": "~9.1.0",
|
|
40
|
+
"@ariestools/sdk": "~8.1.9",
|
|
41
|
+
"@ariestools/toolchain": "~9.1.0",
|
|
42
|
+
"@ariestools/tsconfig": "~9.1.0",
|
|
43
|
+
"@opentelemetry/api": "~1.9.1",
|
|
44
|
+
"@xyo-network/sdk": "~7.2.3",
|
|
45
|
+
"@xyo-network/sdk-protocol": "~7.2.4",
|
|
46
|
+
"@xyo-network/xl1-sdk": "~5.3.1",
|
|
47
|
+
"@xyo-network/xl1-statement-graph-engine": "~0.4.0",
|
|
48
|
+
"@xyo-network/xl1-statement-graph-schemas": "~0.4.0",
|
|
49
|
+
"@xyo-network/xl1-statement-graph-sdk": "~0.4.0",
|
|
50
|
+
"@xyo-network/xl1-statement-graph-testing": "~0.4.0",
|
|
51
|
+
"async-mutex": "~0.5.0",
|
|
52
|
+
"eslint": "~10.8.1",
|
|
53
|
+
"eslint-import-resolver-typescript": "~4.4.5",
|
|
54
|
+
"ethers": "~6.17.0",
|
|
55
|
+
"typescript": "~6.0.3",
|
|
56
|
+
"vite": "~8.2.1",
|
|
57
|
+
"vitest": "~4.1.11",
|
|
58
|
+
"zod": "~4.4.3",
|
|
59
|
+
"@xyo-network/event-kit-schemas": "~0.0.1"
|
|
60
|
+
},
|
|
61
|
+
"peerDependencies": {
|
|
62
|
+
"@ariestools/sdk": "^8.1",
|
|
63
|
+
"@opentelemetry/api": "^1.9",
|
|
64
|
+
"@xyo-network/sdk": "^7.2",
|
|
65
|
+
"@xyo-network/sdk-protocol": "^7.2",
|
|
66
|
+
"@xyo-network/xl1-statement-graph-engine": "^0.4",
|
|
67
|
+
"zod": "^4.4"
|
|
68
|
+
},
|
|
69
|
+
"engines": {
|
|
70
|
+
"node": ">=22"
|
|
71
|
+
},
|
|
72
|
+
"publishConfig": {
|
|
73
|
+
"access": "restricted"
|
|
74
|
+
},
|
|
75
|
+
"scripts": {
|
|
76
|
+
"test": "vitest run"
|
|
77
|
+
}
|
|
78
|
+
}
|