@amalgm/live 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/PURPOSE.md +103 -0
- package/README.md +45 -0
- package/dist/contracts/binding.d.ts +49 -0
- package/dist/contracts/binding.d.ts.map +1 -0
- package/dist/contracts/binding.js +23 -0
- package/dist/contracts/binding.js.map +1 -0
- package/dist/contracts/content.d.ts +42 -0
- package/dist/contracts/content.d.ts.map +1 -0
- package/dist/contracts/content.js +72 -0
- package/dist/contracts/content.js.map +1 -0
- package/dist/contracts/docs.d.ts +64 -0
- package/dist/contracts/docs.d.ts.map +1 -0
- package/dist/contracts/docs.js +51 -0
- package/dist/contracts/docs.js.map +1 -0
- package/dist/contracts/events.d.ts +45 -0
- package/dist/contracts/events.d.ts.map +1 -0
- package/dist/contracts/events.js +38 -0
- package/dist/contracts/events.js.map +1 -0
- package/dist/contracts/frames/gateway.d.ts +83 -0
- package/dist/contracts/frames/gateway.d.ts.map +1 -0
- package/dist/contracts/frames/gateway.js +35 -0
- package/dist/contracts/frames/gateway.js.map +1 -0
- package/dist/contracts/frames/stream.d.ts +59 -0
- package/dist/contracts/frames/stream.d.ts.map +1 -0
- package/dist/contracts/frames/stream.js +17 -0
- package/dist/contracts/frames/stream.js.map +1 -0
- package/dist/contracts/frames/tunnel.d.ts +78 -0
- package/dist/contracts/frames/tunnel.d.ts.map +1 -0
- package/dist/contracts/frames/tunnel.js +55 -0
- package/dist/contracts/frames/tunnel.js.map +1 -0
- package/dist/contracts/index.d.ts +19 -0
- package/dist/contracts/index.d.ts.map +1 -0
- package/dist/contracts/index.js +19 -0
- package/dist/contracts/index.js.map +1 -0
- package/dist/contracts/mutation.d.ts +51 -0
- package/dist/contracts/mutation.d.ts.map +1 -0
- package/dist/contracts/mutation.js +55 -0
- package/dist/contracts/mutation.js.map +1 -0
- package/dist/contracts/presence.d.ts +46 -0
- package/dist/contracts/presence.d.ts.map +1 -0
- package/dist/contracts/presence.js +34 -0
- package/dist/contracts/presence.js.map +1 -0
- package/dist/contracts/resources.d.ts +52 -0
- package/dist/contracts/resources.d.ts.map +1 -0
- package/dist/contracts/resources.js +105 -0
- package/dist/contracts/resources.js.map +1 -0
- package/dist/contracts/snapshot.d.ts +24 -0
- package/dist/contracts/snapshot.d.ts.map +1 -0
- package/dist/contracts/snapshot.js +28 -0
- package/dist/contracts/snapshot.js.map +1 -0
- package/dist/contracts/validate.d.ts +32 -0
- package/dist/contracts/validate.d.ts.map +1 -0
- package/dist/contracts/validate.js +25 -0
- package/dist/contracts/validate.js.map +1 -0
- package/dist/detection/adapter-contract.d.ts +134 -0
- package/dist/detection/adapter-contract.d.ts.map +1 -0
- package/dist/detection/adapter-contract.js +162 -0
- package/dist/detection/adapter-contract.js.map +1 -0
- package/dist/detection/classify.d.ts +31 -0
- package/dist/detection/classify.d.ts.map +1 -0
- package/dist/detection/classify.js +28 -0
- package/dist/detection/classify.js.map +1 -0
- package/dist/detection/continuity.d.ts +54 -0
- package/dist/detection/continuity.d.ts.map +1 -0
- package/dist/detection/continuity.js +85 -0
- package/dist/detection/continuity.js.map +1 -0
- package/dist/detection/coverage.d.ts +43 -0
- package/dist/detection/coverage.d.ts.map +1 -0
- package/dist/detection/coverage.js +60 -0
- package/dist/detection/coverage.js.map +1 -0
- package/dist/detection/diff.d.ts +144 -0
- package/dist/detection/diff.d.ts.map +1 -0
- package/dist/detection/diff.js +187 -0
- package/dist/detection/diff.js.map +1 -0
- package/dist/detection/enrollment.d.ts +16 -0
- package/dist/detection/enrollment.d.ts.map +1 -0
- package/dist/detection/enrollment.js +70 -0
- package/dist/detection/enrollment.js.map +1 -0
- package/dist/detection/index.d.ts +29 -0
- package/dist/detection/index.d.ts.map +1 -0
- package/dist/detection/index.js +29 -0
- package/dist/detection/index.js.map +1 -0
- package/dist/detection/refusal.d.ts +33 -0
- package/dist/detection/refusal.d.ts.map +1 -0
- package/dist/detection/refusal.js +40 -0
- package/dist/detection/refusal.js.map +1 -0
- package/dist/entities/bytes.d.ts +18 -0
- package/dist/entities/bytes.d.ts.map +1 -0
- package/dist/entities/bytes.js +61 -0
- package/dist/entities/bytes.js.map +1 -0
- package/dist/entities/cloud.d.ts +82 -0
- package/dist/entities/cloud.d.ts.map +1 -0
- package/dist/entities/cloud.js +136 -0
- package/dist/entities/cloud.js.map +1 -0
- package/dist/entities/index.d.ts +23 -0
- package/dist/entities/index.d.ts.map +1 -0
- package/dist/entities/index.js +23 -0
- package/dist/entities/index.js.map +1 -0
- package/dist/entities/moves.d.ts +42 -0
- package/dist/entities/moves.d.ts.map +1 -0
- package/dist/entities/moves.js +82 -0
- package/dist/entities/moves.js.map +1 -0
- package/dist/entities/repo-states.d.ts +121 -0
- package/dist/entities/repo-states.d.ts.map +1 -0
- package/dist/entities/repo-states.js +127 -0
- package/dist/entities/repo-states.js.map +1 -0
- package/dist/entities/rules.d.ts +104 -0
- package/dist/entities/rules.d.ts.map +1 -0
- package/dist/entities/rules.js +200 -0
- package/dist/entities/rules.js.map +1 -0
- package/dist/entities/types.d.ts +94 -0
- package/dist/entities/types.d.ts.map +1 -0
- package/dist/entities/types.js +40 -0
- package/dist/entities/types.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/machines/arbitration.d.ts +36 -0
- package/dist/machines/arbitration.d.ts.map +1 -0
- package/dist/machines/arbitration.js +37 -0
- package/dist/machines/arbitration.js.map +1 -0
- package/dist/machines/backoff.d.ts +36 -0
- package/dist/machines/backoff.d.ts.map +1 -0
- package/dist/machines/backoff.js +34 -0
- package/dist/machines/backoff.js.map +1 -0
- package/dist/machines/bootstrap.d.ts +65 -0
- package/dist/machines/bootstrap.d.ts.map +1 -0
- package/dist/machines/bootstrap.js +105 -0
- package/dist/machines/bootstrap.js.map +1 -0
- package/dist/machines/chunks.d.ts +51 -0
- package/dist/machines/chunks.d.ts.map +1 -0
- package/dist/machines/chunks.js +67 -0
- package/dist/machines/chunks.js.map +1 -0
- package/dist/machines/index.d.ts +14 -0
- package/dist/machines/index.d.ts.map +1 -0
- package/dist/machines/index.js +14 -0
- package/dist/machines/index.js.map +1 -0
- package/dist/machines/journal.d.ts +63 -0
- package/dist/machines/journal.d.ts.map +1 -0
- package/dist/machines/journal.js +71 -0
- package/dist/machines/journal.js.map +1 -0
- package/dist/machines/ordering.d.ts +53 -0
- package/dist/machines/ordering.d.ts.map +1 -0
- package/dist/machines/ordering.js +87 -0
- package/dist/machines/ordering.js.map +1 -0
- package/dist/machines/presence.d.ts +26 -0
- package/dist/machines/presence.d.ts.map +1 -0
- package/dist/machines/presence.js +49 -0
- package/dist/machines/presence.js.map +1 -0
- package/dist/merge/index.d.ts +9 -0
- package/dist/merge/index.d.ts.map +1 -0
- package/dist/merge/index.js +9 -0
- package/dist/merge/index.js.map +1 -0
- package/dist/merge/merge3.d.ts +39 -0
- package/dist/merge/merge3.d.ts.map +1 -0
- package/dist/merge/merge3.js +188 -0
- package/dist/merge/merge3.js.map +1 -0
- package/package.json +48 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Amalgm's default enrollment policy: which relative paths receive
|
|
3
|
+
* workspace identities. Ratified by entity-model.md axiom 2 — amalgm's
|
|
4
|
+
* manual enrollment policy decides what enrolls; external conventions
|
|
5
|
+
* (gitignore) may inform it, never decide it implicitly.
|
|
6
|
+
*
|
|
7
|
+
* Machine-local metadata, dependencies, generated caches, and secrets
|
|
8
|
+
* never receive workspace identities. The rule applies at every depth.
|
|
9
|
+
* Pure string policy: a host may inject its own `EnrollmentPolicy`
|
|
10
|
+
* everywhere this default is accepted.
|
|
11
|
+
*/
|
|
12
|
+
/** The injected policy shape: relative path in, verdict out. */
|
|
13
|
+
export type EnrollmentPolicy = (relPath: string) => boolean;
|
|
14
|
+
/** The default policy. Both separators are path separators; '' never enrolls. */
|
|
15
|
+
export declare const defaultShouldEnroll: EnrollmentPolicy;
|
|
16
|
+
//# sourceMappingURL=enrollment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enrollment.d.ts","sourceRoot":"","sources":["../../src/detection/enrollment.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,gEAAgE;AAChE,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;AAgD5D,iFAAiF;AACjF,eAAO,MAAM,mBAAmB,EAAE,gBAMjC,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Amalgm's default enrollment policy: which relative paths receive
|
|
3
|
+
* workspace identities. Ratified by entity-model.md axiom 2 — amalgm's
|
|
4
|
+
* manual enrollment policy decides what enrolls; external conventions
|
|
5
|
+
* (gitignore) may inform it, never decide it implicitly.
|
|
6
|
+
*
|
|
7
|
+
* Machine-local metadata, dependencies, generated caches, and secrets
|
|
8
|
+
* never receive workspace identities. The rule applies at every depth.
|
|
9
|
+
* Pure string policy: a host may inject its own `EnrollmentPolicy`
|
|
10
|
+
* everywhere this default is accepted.
|
|
11
|
+
*/
|
|
12
|
+
const EXCLUDED_DIRECTORIES = new Set([
|
|
13
|
+
'.amalgm',
|
|
14
|
+
'.aws',
|
|
15
|
+
'.cache',
|
|
16
|
+
'.docker',
|
|
17
|
+
'.git',
|
|
18
|
+
'.gnupg',
|
|
19
|
+
'.gradle',
|
|
20
|
+
'.hg',
|
|
21
|
+
'.kube',
|
|
22
|
+
'.mypy_cache',
|
|
23
|
+
'.next',
|
|
24
|
+
'.nyc_output',
|
|
25
|
+
'.parcel-cache',
|
|
26
|
+
'.pytest_cache',
|
|
27
|
+
'.ruff_cache',
|
|
28
|
+
'.ssh',
|
|
29
|
+
'.svn',
|
|
30
|
+
'.svelte-kit',
|
|
31
|
+
'.turbo',
|
|
32
|
+
'.venv',
|
|
33
|
+
'.vite',
|
|
34
|
+
'__pycache__',
|
|
35
|
+
'coverage',
|
|
36
|
+
'node_modules',
|
|
37
|
+
]);
|
|
38
|
+
const EXCLUDED_FILES = new Set([
|
|
39
|
+
'.DS_Store',
|
|
40
|
+
'Thumbs.db',
|
|
41
|
+
'desktop.ini',
|
|
42
|
+
'npm-debug.log',
|
|
43
|
+
'pnpm-debug.log',
|
|
44
|
+
'yarn-debug.log',
|
|
45
|
+
'yarn-error.log',
|
|
46
|
+
]);
|
|
47
|
+
function isPrivateFile(name) {
|
|
48
|
+
if (/^\.env(?:\..+)?$/i.test(name) && !/\.example$/i.test(name))
|
|
49
|
+
return true;
|
|
50
|
+
if (/^(?:credentials?|secrets?)\.(?:json|ya?ml|toml|ini|conf)$/i.test(name))
|
|
51
|
+
return true;
|
|
52
|
+
if (/^id_(?:dsa|ecdsa|ed25519|rsa)$/i.test(name))
|
|
53
|
+
return true;
|
|
54
|
+
if (/^(?:\.git-credentials|\.netrc|\.npmrc|\.pypirc|auth\.json|kubeconfig)$/i.test(name))
|
|
55
|
+
return true;
|
|
56
|
+
if (/^(?:service[-_]?account|firebase[-_]?adminsdk).*\.json$/i.test(name))
|
|
57
|
+
return true;
|
|
58
|
+
return /\.(?:key|keystore|kdbx|p12|pfx|pem|ppk|tfstate(?:\.backup)?)$/i.test(name);
|
|
59
|
+
}
|
|
60
|
+
/** The default policy. Both separators are path separators; '' never enrolls. */
|
|
61
|
+
export const defaultShouldEnroll = (relPath) => {
|
|
62
|
+
const parts = relPath.split(/[\\/]/).filter(Boolean);
|
|
63
|
+
const name = parts.at(-1);
|
|
64
|
+
if (name === undefined || parts.some((part) => EXCLUDED_DIRECTORIES.has(part)))
|
|
65
|
+
return false;
|
|
66
|
+
if (EXCLUDED_FILES.has(name) || isPrivateFile(name))
|
|
67
|
+
return false;
|
|
68
|
+
return !name.startsWith('.#') && !name.endsWith('~') && !/\.(?:swp|swo)$/i.test(name);
|
|
69
|
+
};
|
|
70
|
+
//# sourceMappingURL=enrollment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enrollment.js","sourceRoot":"","sources":["../../src/detection/enrollment.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,MAAM,oBAAoB,GAAG,IAAI,GAAG,CAAC;IACnC,SAAS;IACT,MAAM;IACN,QAAQ;IACR,SAAS;IACT,MAAM;IACN,QAAQ;IACR,SAAS;IACT,KAAK;IACL,OAAO;IACP,aAAa;IACb,OAAO;IACP,aAAa;IACb,eAAe;IACf,eAAe;IACf,aAAa;IACb,MAAM;IACN,MAAM;IACN,aAAa;IACb,QAAQ;IACR,OAAO;IACP,OAAO;IACP,aAAa;IACb,UAAU;IACV,cAAc;CACf,CAAC,CAAC;AAEH,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC;IAC7B,WAAW;IACX,WAAW;IACX,aAAa;IACb,eAAe;IACf,gBAAgB;IAChB,gBAAgB;IAChB,gBAAgB;CACjB,CAAC,CAAC;AAEH,SAAS,aAAa,CAAC,IAAY;IACjC,IAAI,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC7E,IAAI,4DAA4D,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACzF,IAAI,iCAAiC,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC9D,IAAI,yEAAyE,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACtG,IAAI,0DAA0D,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACvF,OAAO,gEAAgE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACrF,CAAC;AAED,iFAAiF;AACjF,MAAM,CAAC,MAAM,mBAAmB,GAAqB,CAAC,OAAO,EAAE,EAAE;IAC/D,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACrD,MAAM,IAAI,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1B,IAAI,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,oBAAoB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAC7F,IAAI,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,aAAa,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAClE,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACxF,CAAC,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detection — the pure cores of the Watch/Detect rails, ported from the
|
|
3
|
+
* engine's observer and registration boundary. Normative sources:
|
|
4
|
+
* entity-model.md (identity axioms, the two continuity witnesses) and
|
|
5
|
+
* entity-implementation.md (the ratified seams).
|
|
6
|
+
*
|
|
7
|
+
* Everything here is rows and entries in, verdicts out. Walking disk,
|
|
8
|
+
* hashing bytes, opening watchers, and writing stores are the host's;
|
|
9
|
+
* the host injects its answers (a stat, a channel row, an enrollment
|
|
10
|
+
* policy) and this layer owns only the laws:
|
|
11
|
+
*
|
|
12
|
+
* - `adapter-contract` the seven rails, the ratified detect socket,
|
|
13
|
+
* descriptor conviction, the three-state truth
|
|
14
|
+
* judgment, the reference adapter
|
|
15
|
+
* - `classify` text/binary from detect's own read evidence
|
|
16
|
+
* - `refusal` declined-vs-broken, named where it is raised
|
|
17
|
+
* - `enrollment` the default manual enrollment policy
|
|
18
|
+
* - `diff` the compare functions: file/dir/link identity
|
|
19
|
+
* - `coverage` one OS watcher per outermost tree
|
|
20
|
+
* - `continuity` root rescue and the undecided address
|
|
21
|
+
*/
|
|
22
|
+
export * from './adapter-contract.js';
|
|
23
|
+
export * from './classify.js';
|
|
24
|
+
export * from './continuity.js';
|
|
25
|
+
export * from './coverage.js';
|
|
26
|
+
export * from './diff.js';
|
|
27
|
+
export * from './enrollment.js';
|
|
28
|
+
export * from './refusal.js';
|
|
29
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/detection/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detection — the pure cores of the Watch/Detect rails, ported from the
|
|
3
|
+
* engine's observer and registration boundary. Normative sources:
|
|
4
|
+
* entity-model.md (identity axioms, the two continuity witnesses) and
|
|
5
|
+
* entity-implementation.md (the ratified seams).
|
|
6
|
+
*
|
|
7
|
+
* Everything here is rows and entries in, verdicts out. Walking disk,
|
|
8
|
+
* hashing bytes, opening watchers, and writing stores are the host's;
|
|
9
|
+
* the host injects its answers (a stat, a channel row, an enrollment
|
|
10
|
+
* policy) and this layer owns only the laws:
|
|
11
|
+
*
|
|
12
|
+
* - `adapter-contract` the seven rails, the ratified detect socket,
|
|
13
|
+
* descriptor conviction, the three-state truth
|
|
14
|
+
* judgment, the reference adapter
|
|
15
|
+
* - `classify` text/binary from detect's own read evidence
|
|
16
|
+
* - `refusal` declined-vs-broken, named where it is raised
|
|
17
|
+
* - `enrollment` the default manual enrollment policy
|
|
18
|
+
* - `diff` the compare functions: file/dir/link identity
|
|
19
|
+
* - `coverage` one OS watcher per outermost tree
|
|
20
|
+
* - `continuity` root rescue and the undecided address
|
|
21
|
+
*/
|
|
22
|
+
export * from './adapter-contract.js';
|
|
23
|
+
export * from './classify.js';
|
|
24
|
+
export * from './continuity.js';
|
|
25
|
+
export * from './coverage.js';
|
|
26
|
+
export * from './diff.js';
|
|
27
|
+
export * from './enrollment.js';
|
|
28
|
+
export * from './refusal.js';
|
|
29
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/detection/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A REFUSAL: the boundary understood the request and declined it.
|
|
3
|
+
* Ratified by entity-implementation.md ("A refusal is named where it is
|
|
4
|
+
* raised").
|
|
5
|
+
*
|
|
6
|
+
* Two things can go wrong when a caller asks for something, and they
|
|
7
|
+
* mean opposite things:
|
|
8
|
+
*
|
|
9
|
+
* a refusal the request named ground amalgm will not take — excluded
|
|
10
|
+
* by enrollment policy, already owned by another tree, not
|
|
11
|
+
* there at all. Nothing is broken. The message IS the
|
|
12
|
+
* reason and is meant to be shown to whoever asked.
|
|
13
|
+
* a fault the boundary could not do its job — a torn identity
|
|
14
|
+
* store, an unusable database, a bug. The request was
|
|
15
|
+
* fine; the installation is not.
|
|
16
|
+
*
|
|
17
|
+
* A refusal is NAMED WHERE IT IS RAISED, by the code that decided to
|
|
18
|
+
* refuse. It is never guessed later from an error's wording: matching
|
|
19
|
+
* on message text would quietly reclassify every fault as the caller's
|
|
20
|
+
* mistake the moment a message changed, and "your path is bad" is the
|
|
21
|
+
* worst possible thing to say on the day the identity store tears.
|
|
22
|
+
*
|
|
23
|
+
* Callers that must answer differently — an HTTP status, an exit code —
|
|
24
|
+
* ask `isRefusal`. Everything else stays an ordinary Error and travels
|
|
25
|
+
* to whatever handles faults. The mark is a registry symbol
|
|
26
|
+
* (`Symbol.for`), so a refusal raised by one copy of this module is
|
|
27
|
+
* recognized by every other.
|
|
28
|
+
*/
|
|
29
|
+
/** Decline a request, with the reason the caller should be shown. */
|
|
30
|
+
export declare function refusal(message: string): Error;
|
|
31
|
+
/** True only for an error this boundary deliberately raised as a refusal. */
|
|
32
|
+
export declare function isRefusal(error: unknown): boolean;
|
|
33
|
+
//# sourceMappingURL=refusal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refusal.d.ts","sourceRoot":"","sources":["../../src/detection/refusal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAIH,qEAAqE;AACrE,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,CAI9C;AAED,6EAA6E;AAC7E,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEjD"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A REFUSAL: the boundary understood the request and declined it.
|
|
3
|
+
* Ratified by entity-implementation.md ("A refusal is named where it is
|
|
4
|
+
* raised").
|
|
5
|
+
*
|
|
6
|
+
* Two things can go wrong when a caller asks for something, and they
|
|
7
|
+
* mean opposite things:
|
|
8
|
+
*
|
|
9
|
+
* a refusal the request named ground amalgm will not take — excluded
|
|
10
|
+
* by enrollment policy, already owned by another tree, not
|
|
11
|
+
* there at all. Nothing is broken. The message IS the
|
|
12
|
+
* reason and is meant to be shown to whoever asked.
|
|
13
|
+
* a fault the boundary could not do its job — a torn identity
|
|
14
|
+
* store, an unusable database, a bug. The request was
|
|
15
|
+
* fine; the installation is not.
|
|
16
|
+
*
|
|
17
|
+
* A refusal is NAMED WHERE IT IS RAISED, by the code that decided to
|
|
18
|
+
* refuse. It is never guessed later from an error's wording: matching
|
|
19
|
+
* on message text would quietly reclassify every fault as the caller's
|
|
20
|
+
* mistake the moment a message changed, and "your path is bad" is the
|
|
21
|
+
* worst possible thing to say on the day the identity store tears.
|
|
22
|
+
*
|
|
23
|
+
* Callers that must answer differently — an HTTP status, an exit code —
|
|
24
|
+
* ask `isRefusal`. Everything else stays an ordinary Error and travels
|
|
25
|
+
* to whatever handles faults. The mark is a registry symbol
|
|
26
|
+
* (`Symbol.for`), so a refusal raised by one copy of this module is
|
|
27
|
+
* recognized by every other.
|
|
28
|
+
*/
|
|
29
|
+
const REFUSAL = Symbol.for('amalgm.registration.refusal');
|
|
30
|
+
/** Decline a request, with the reason the caller should be shown. */
|
|
31
|
+
export function refusal(message) {
|
|
32
|
+
const error = new Error(message);
|
|
33
|
+
error[REFUSAL] = true;
|
|
34
|
+
return error;
|
|
35
|
+
}
|
|
36
|
+
/** True only for an error this boundary deliberately raised as a refusal. */
|
|
37
|
+
export function isRefusal(error) {
|
|
38
|
+
return Boolean(error && error[REFUSAL]);
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=refusal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refusal.js","sourceRoot":"","sources":["../../src/detection/refusal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,MAAM,OAAO,GAAkB,MAAM,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;AAEzE,qEAAqE;AACrE,MAAM,UAAU,OAAO,CAAC,OAAe;IACrC,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,OAAO,CAAgC,CAAC;IAChE,KAAK,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;IACtB,OAAO,KAAK,CAAC;AACf,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,SAAS,CAAC,KAAc;IACtC,OAAO,OAAO,CAAC,KAAK,IAAK,KAAiC,CAAC,OAAO,CAAC,CAAC,CAAC;AACvE,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Portable byte codecs shared by the entity layer — UTF-8, standard base64
|
|
3
|
+
* (padded, as Node's `Buffer#toString('base64')` emits it), base64url, and
|
|
4
|
+
* hex. They exist so cloud.ts and repo-states.ts can produce byte-for-byte
|
|
5
|
+
* the same wire text the engine produces with Buffer, without src/
|
|
6
|
+
* importing any Node module (PURPOSE.md axiom 2).
|
|
7
|
+
*/
|
|
8
|
+
export declare const utf8Encode: (text: string) => Uint8Array;
|
|
9
|
+
export declare const utf8Decode: (bytes: Uint8Array) => string;
|
|
10
|
+
/** Bytes → standard base64 with padding (Buffer's 'base64' spelling). */
|
|
11
|
+
export declare const bytesToBase64: (bytes: Uint8Array) => string;
|
|
12
|
+
/** Bytes → unpadded base64url (Buffer's 'base64url' spelling). */
|
|
13
|
+
export declare const bytesToBase64Url: (bytes: Uint8Array) => string;
|
|
14
|
+
/** Standard base64 (padded or unpadded) → bytes. */
|
|
15
|
+
export declare function base64ToBytes(text: string): Uint8Array;
|
|
16
|
+
/** Lowercase/uppercase hex → bytes. */
|
|
17
|
+
export declare function hexToBytes(hex: string): Uint8Array;
|
|
18
|
+
//# sourceMappingURL=bytes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bytes.d.ts","sourceRoot":"","sources":["../../src/entities/bytes.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,eAAO,MAAM,UAAU,GAAI,MAAM,MAAM,KAAG,UAA4C,CAAC;AAEvF,eAAO,MAAM,UAAU,GAAI,OAAO,UAAU,KAAG,MAAyC,CAAC;AAgBzF,yEAAyE;AACzE,eAAO,MAAM,aAAa,GAAI,OAAO,UAAU,KAAG,MAAqC,CAAC;AAExF,kEAAkE;AAClE,eAAO,MAAM,gBAAgB,GAAI,OAAO,UAAU,KAAG,MAA0C,CAAC;AAEhG,oDAAoD;AACpD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAkBtD;AAED,uCAAuC;AACvC,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CASlD"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Portable byte codecs shared by the entity layer — UTF-8, standard base64
|
|
3
|
+
* (padded, as Node's `Buffer#toString('base64')` emits it), base64url, and
|
|
4
|
+
* hex. They exist so cloud.ts and repo-states.ts can produce byte-for-byte
|
|
5
|
+
* the same wire text the engine produces with Buffer, without src/
|
|
6
|
+
* importing any Node module (PURPOSE.md axiom 2).
|
|
7
|
+
*/
|
|
8
|
+
const BASE64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
|
9
|
+
const BASE64_URL = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
|
|
10
|
+
export const utf8Encode = (text) => new TextEncoder().encode(text);
|
|
11
|
+
export const utf8Decode = (bytes) => new TextDecoder().decode(bytes);
|
|
12
|
+
function encode(bytes, alphabet, pad) {
|
|
13
|
+
let out = '';
|
|
14
|
+
for (let i = 0; i < bytes.length; i += 3) {
|
|
15
|
+
const a = bytes[i];
|
|
16
|
+
const b = bytes[i + 1];
|
|
17
|
+
const c = bytes[i + 2];
|
|
18
|
+
out += alphabet[a >> 2];
|
|
19
|
+
out += alphabet[((a & 0x03) << 4) | ((b ?? 0) >> 4)];
|
|
20
|
+
out += b === undefined ? (pad ? '=' : '') : alphabet[((b & 0x0f) << 2) | ((c ?? 0) >> 6)];
|
|
21
|
+
out += c === undefined ? (pad ? '=' : '') : alphabet[c & 0x3f];
|
|
22
|
+
}
|
|
23
|
+
return out;
|
|
24
|
+
}
|
|
25
|
+
/** Bytes → standard base64 with padding (Buffer's 'base64' spelling). */
|
|
26
|
+
export const bytesToBase64 = (bytes) => encode(bytes, BASE64, true);
|
|
27
|
+
/** Bytes → unpadded base64url (Buffer's 'base64url' spelling). */
|
|
28
|
+
export const bytesToBase64Url = (bytes) => encode(bytes, BASE64_URL, false);
|
|
29
|
+
/** Standard base64 (padded or unpadded) → bytes. */
|
|
30
|
+
export function base64ToBytes(text) {
|
|
31
|
+
const out = [];
|
|
32
|
+
let buffer = 0;
|
|
33
|
+
let bits = 0;
|
|
34
|
+
for (const char of text) {
|
|
35
|
+
if (char === '=')
|
|
36
|
+
break; // padding ends the payload
|
|
37
|
+
const value = BASE64.indexOf(char);
|
|
38
|
+
if (value === -1) {
|
|
39
|
+
throw new Error(`expected standard base64 like "aGVsbG8=" — found ${JSON.stringify(char)}`);
|
|
40
|
+
}
|
|
41
|
+
buffer = (buffer << 6) | value;
|
|
42
|
+
bits += 6;
|
|
43
|
+
if (bits >= 8) {
|
|
44
|
+
bits -= 8;
|
|
45
|
+
out.push((buffer >> bits) & 0xff);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return new Uint8Array(out);
|
|
49
|
+
}
|
|
50
|
+
/** Lowercase/uppercase hex → bytes. */
|
|
51
|
+
export function hexToBytes(hex) {
|
|
52
|
+
if (hex.length % 2 !== 0 || /[^0-9a-f]/i.test(hex)) {
|
|
53
|
+
throw new Error(`expected even-length hex like "a1b2" — got ${JSON.stringify(hex)}`);
|
|
54
|
+
}
|
|
55
|
+
const out = new Uint8Array(hex.length / 2);
|
|
56
|
+
for (let i = 0; i < out.length; i += 1) {
|
|
57
|
+
out[i] = Number.parseInt(hex.slice(i * 2, i * 2 + 2), 16);
|
|
58
|
+
}
|
|
59
|
+
return out;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=bytes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bytes.js","sourceRoot":"","sources":["../../src/entities/bytes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The entity-cloud boundary's pure half (engine
|
|
3
|
+
* registration/entity-cloud.js): the snapshot codec, record assertions,
|
|
4
|
+
* equality, the private resource id, and the repo travel law — only
|
|
5
|
+
* logical graph facts, never a path, inode, watcher, or database row.
|
|
6
|
+
*
|
|
7
|
+
* Wire parity is the contract here: `stableJson`, record key order, and
|
|
8
|
+
* snapshot sorting reproduce the engine's bytes exactly, so a snapshot
|
|
9
|
+
* packed on either side hashes and compares identically.
|
|
10
|
+
*/
|
|
11
|
+
import { type EntityStatus, type EntityType, type Sha256Hex } from './types.js';
|
|
12
|
+
/** `@1` could project arbitrary pre-cloud registrations. `@2` omitted the
|
|
13
|
+
* declared built-in tool entities, so its toolbox root could not prove the
|
|
14
|
+
* snapshot membership it named. A resource contract names immutable
|
|
15
|
+
* authority semantics: both remain quarantined rather than reinterpreted
|
|
16
|
+
* or overwritten. `@3` begins with the complete verified user home; later
|
|
17
|
+
* user ground enters exclusively through `amalgm register`. */
|
|
18
|
+
export declare const ENTITY_CLOUD_CONTRACT = "amalgm-entity-registry@3";
|
|
19
|
+
export declare const ENTITY_CLOUD_SCHEMA_VERSION = 1;
|
|
20
|
+
/** The record as it travels in a cloud snapshot: the six fields, the leaf
|
|
21
|
+
* head, and — for repositories only — the immutable transport head naming
|
|
22
|
+
* the Card + Checkpoint parcel. */
|
|
23
|
+
export interface CloudEntityRecord {
|
|
24
|
+
readonly uuid: string;
|
|
25
|
+
readonly type: EntityType;
|
|
26
|
+
readonly parentUUID: string | null;
|
|
27
|
+
readonly name: string;
|
|
28
|
+
readonly status: EntityStatus;
|
|
29
|
+
readonly version: string;
|
|
30
|
+
readonly payloadVersion: string | null;
|
|
31
|
+
readonly transportVersion: string | null;
|
|
32
|
+
}
|
|
33
|
+
export interface CloudSnapshot {
|
|
34
|
+
readonly schemaVersion: number;
|
|
35
|
+
readonly kind: 'amalgm-entity-registry';
|
|
36
|
+
readonly records: readonly CloudEntityRecord[];
|
|
37
|
+
}
|
|
38
|
+
/** The deterministic private entity-resource id for a user under the
|
|
39
|
+
* current contract: `pvr_` + the first 32 base64url characters of
|
|
40
|
+
* sha256("private-user:<userId>:<contract>"). */
|
|
41
|
+
export declare function privateEntityResourceId(userId: string, sha256Hex: Sha256Hex): string;
|
|
42
|
+
/** The one JSON spelling every snapshot comparison and checksum uses. */
|
|
43
|
+
export declare const stableJson: (value: unknown) => string;
|
|
44
|
+
export declare const sameRecord: (left: unknown, right: unknown) => boolean;
|
|
45
|
+
/** Two record lists describe the same graph (normalized, sorted, compared whole). */
|
|
46
|
+
export declare const sameRecords: (left: readonly unknown[], right: readonly unknown[]) => boolean;
|
|
47
|
+
/** Every record in `records` appears byte-identically in `expected`. */
|
|
48
|
+
export declare function recordsAreSubset(records: readonly unknown[], expected: readonly unknown[]): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Validate one snapshot record and normalize it (UUIDs lowercased,
|
|
51
|
+
* transportVersion defaulted to null). Refusals: an invalid shape; a
|
|
52
|
+
* parentless record whose type no tree root wears; a transport head on
|
|
53
|
+
* anything but a repository.
|
|
54
|
+
*/
|
|
55
|
+
export declare function assertRecord(value: unknown): CloudEntityRecord;
|
|
56
|
+
/** How an enclosing lookup answers: the parent record's type and its own
|
|
57
|
+
* parent, or null/undefined for missing ancestry. */
|
|
58
|
+
export type CloudAncestorLookup = (uuid: string) => {
|
|
59
|
+
readonly type: string;
|
|
60
|
+
readonly parentUUID: string | null | undefined;
|
|
61
|
+
} | null | undefined;
|
|
62
|
+
/**
|
|
63
|
+
* The repo travel law: a record with a `repo.git` PROPER ancestor never
|
|
64
|
+
* travels to the cloud on its own. The repository is the sync boundary —
|
|
65
|
+
* its one Card + Checkpoint state carries the worktree's bytes AND its
|
|
66
|
+
* children's permanent UUIDs (the transport identity map), so a register
|
|
67
|
+
* or a rebase is one parcel, never one postcard per file. A nested
|
|
68
|
+
* repository inside another repo's worktree is enclosed too: it becomes
|
|
69
|
+
* cloud-visible only when registered explicitly as its own tree.
|
|
70
|
+
* Missing ancestry keeps the record traveling rather than risking a
|
|
71
|
+
* silently unsynced entity.
|
|
72
|
+
*/
|
|
73
|
+
export declare function enclosedByRepositoryAncestor(record: {
|
|
74
|
+
readonly uuid: string;
|
|
75
|
+
readonly parentUUID: string | null | undefined;
|
|
76
|
+
}, lookup: CloudAncestorLookup): boolean;
|
|
77
|
+
/** Normalize records into the one canonical snapshot: asserted, sorted by
|
|
78
|
+
* uuid, duplicates refused. */
|
|
79
|
+
export declare function snapshotFromRecords(records: readonly unknown[]): CloudSnapshot;
|
|
80
|
+
/** Parse snapshot bytes (or their UTF-8 text) back into the canonical form. */
|
|
81
|
+
export declare function parseSnapshot(bytes: Uint8Array | string): CloudSnapshot;
|
|
82
|
+
//# sourceMappingURL=cloud.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloud.d.ts","sourceRoot":"","sources":["../../src/entities/cloud.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAmC,KAAK,YAAY,EAAE,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAGjH;;;;;+DAK+D;AAC/D,eAAO,MAAM,qBAAqB,6BAA6B,CAAC;AAEhE,eAAO,MAAM,2BAA2B,IAAI,CAAC;AAK7C;;mCAEmC;AACnC,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1C;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,IAAI,EAAE,wBAAwB,CAAC;IACxC,QAAQ,CAAC,OAAO,EAAE,SAAS,iBAAiB,EAAE,CAAC;CAChD;AAED;;iDAEiD;AACjD,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,GAAG,MAAM,CAGpF;AAED,yEAAyE;AACzE,eAAO,MAAM,UAAU,GAAI,OAAO,OAAO,KAAG,MAA+B,CAAC;AAE5E,eAAO,MAAM,UAAU,GAAI,MAAM,OAAO,EAAE,OAAO,OAAO,KAAG,OACnB,CAAC;AAEzC,qFAAqF;AACrF,eAAO,MAAM,WAAW,GAAI,MAAM,SAAS,OAAO,EAAE,EAAE,OAAO,SAAS,OAAO,EAAE,KAAG,OACf,CAAC;AAEpE,wEAAwE;AACxE,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,SAAS,OAAO,EAAE,EAAE,QAAQ,EAAE,SAAS,OAAO,EAAE,GAAG,OAAO,CAMnG;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,iBAAiB,CAkC9D;AAED;qDACqD;AACrD,MAAM,MAAM,mBAAmB,GAAG,CAAC,IAAI,EAAE,MAAM,KAC7C;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,CAAC;AAE/F;;;;;;;;;;GAUG;AACH,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAA;CAAE,EACjF,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAYT;AAED;+BAC+B;AAC/B,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,SAAS,OAAO,EAAE,GAAG,aAAa,CAW9E;AAED,+EAA+E;AAC/E,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,GAAG,aAAa,CAavE"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The entity-cloud boundary's pure half (engine
|
|
3
|
+
* registration/entity-cloud.js): the snapshot codec, record assertions,
|
|
4
|
+
* equality, the private resource id, and the repo travel law — only
|
|
5
|
+
* logical graph facts, never a path, inode, watcher, or database row.
|
|
6
|
+
*
|
|
7
|
+
* Wire parity is the contract here: `stableJson`, record key order, and
|
|
8
|
+
* snapshot sorting reproduce the engine's bytes exactly, so a snapshot
|
|
9
|
+
* packed on either side hashes and compares identically.
|
|
10
|
+
*/
|
|
11
|
+
import { ROOT_TYPES, TYPES, UUID_PATTERN } from './types.js';
|
|
12
|
+
import { bytesToBase64Url, hexToBytes, utf8Decode } from './bytes.js';
|
|
13
|
+
/** `@1` could project arbitrary pre-cloud registrations. `@2` omitted the
|
|
14
|
+
* declared built-in tool entities, so its toolbox root could not prove the
|
|
15
|
+
* snapshot membership it named. A resource contract names immutable
|
|
16
|
+
* authority semantics: both remain quarantined rather than reinterpreted
|
|
17
|
+
* or overwritten. `@3` begins with the complete verified user home; later
|
|
18
|
+
* user ground enters exclusively through `amalgm register`. */
|
|
19
|
+
export const ENTITY_CLOUD_CONTRACT = 'amalgm-entity-registry@3';
|
|
20
|
+
export const ENTITY_CLOUD_SCHEMA_VERSION = 1;
|
|
21
|
+
/** A 64-hex content head (a SHA-256 naming immutable bytes). */
|
|
22
|
+
const CONTENT_HEAD = /^[0-9a-f]{64}$/;
|
|
23
|
+
/** The deterministic private entity-resource id for a user under the
|
|
24
|
+
* current contract: `pvr_` + the first 32 base64url characters of
|
|
25
|
+
* sha256("private-user:<userId>:<contract>"). */
|
|
26
|
+
export function privateEntityResourceId(userId, sha256Hex) {
|
|
27
|
+
return `pvr_${bytesToBase64Url(hexToBytes(sha256Hex(`private-user:${userId}:${ENTITY_CLOUD_CONTRACT}`)))
|
|
28
|
+
.slice(0, 32)}`;
|
|
29
|
+
}
|
|
30
|
+
/** The one JSON spelling every snapshot comparison and checksum uses. */
|
|
31
|
+
export const stableJson = (value) => JSON.stringify(value);
|
|
32
|
+
export const sameRecord = (left, right) => stableJson(left) === stableJson(right);
|
|
33
|
+
/** Two record lists describe the same graph (normalized, sorted, compared whole). */
|
|
34
|
+
export const sameRecords = (left, right) => sameRecord(snapshotFromRecords(left), snapshotFromRecords(right));
|
|
35
|
+
/** Every record in `records` appears byte-identically in `expected`. */
|
|
36
|
+
export function recordsAreSubset(records, expected) {
|
|
37
|
+
const expectedByUuid = new Map(snapshotFromRecords(expected).records.map((record) => [record.uuid, record]));
|
|
38
|
+
return snapshotFromRecords(records).records
|
|
39
|
+
.every((record) => sameRecord(record, expectedByUuid.get(record.uuid)));
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Validate one snapshot record and normalize it (UUIDs lowercased,
|
|
43
|
+
* transportVersion defaulted to null). Refusals: an invalid shape; a
|
|
44
|
+
* parentless record whose type no tree root wears; a transport head on
|
|
45
|
+
* anything but a repository.
|
|
46
|
+
*/
|
|
47
|
+
export function assertRecord(value) {
|
|
48
|
+
const record = value;
|
|
49
|
+
if (!record || typeof record !== 'object'
|
|
50
|
+
|| typeof record.uuid !== 'string' || !UUID_PATTERN.test(record.uuid)
|
|
51
|
+
|| typeof record.type !== 'string' || !TYPES.has(record.type)
|
|
52
|
+
|| (record.parentUUID !== null && (typeof record.parentUUID !== 'string' || !UUID_PATTERN.test(record.parentUUID)))
|
|
53
|
+
|| typeof record.name !== 'string' || !record.name || record.name.includes('/') || record.name.includes('\0')
|
|
54
|
+
|| !['active', 'trashed', 'deleted'].includes(record.status)
|
|
55
|
+
|| typeof record.version !== 'string' || !/^[0-9a-f]{64}$/.test(record.version)
|
|
56
|
+
|| (record.payloadVersion !== null && typeof record.payloadVersion !== 'string')
|
|
57
|
+
|| (record.transportVersion !== undefined && record.transportVersion !== null
|
|
58
|
+
&& (typeof record.transportVersion !== 'string' || !CONTENT_HEAD.test(record.transportVersion)))) {
|
|
59
|
+
throw new Error('cloud entity snapshot has an invalid record');
|
|
60
|
+
}
|
|
61
|
+
if (record.parentUUID === null && !ROOT_TYPES.has(record.type)) {
|
|
62
|
+
throw new Error(`cloud entity ${record.uuid} is not a valid tree root`);
|
|
63
|
+
}
|
|
64
|
+
const transportVersion = (record.transportVersion ?? null);
|
|
65
|
+
if (record.type !== 'repo.git' && transportVersion !== null) {
|
|
66
|
+
throw new Error('only repository entities may declare a transport head');
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
uuid: record.uuid.toLowerCase(),
|
|
70
|
+
type: record.type,
|
|
71
|
+
parentUUID: record.parentUUID === null ? null : record.parentUUID.toLowerCase(),
|
|
72
|
+
name: record.name,
|
|
73
|
+
status: record.status,
|
|
74
|
+
version: record.version,
|
|
75
|
+
payloadVersion: record.payloadVersion,
|
|
76
|
+
transportVersion,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* The repo travel law: a record with a `repo.git` PROPER ancestor never
|
|
81
|
+
* travels to the cloud on its own. The repository is the sync boundary —
|
|
82
|
+
* its one Card + Checkpoint state carries the worktree's bytes AND its
|
|
83
|
+
* children's permanent UUIDs (the transport identity map), so a register
|
|
84
|
+
* or a rebase is one parcel, never one postcard per file. A nested
|
|
85
|
+
* repository inside another repo's worktree is enclosed too: it becomes
|
|
86
|
+
* cloud-visible only when registered explicitly as its own tree.
|
|
87
|
+
* Missing ancestry keeps the record traveling rather than risking a
|
|
88
|
+
* silently unsynced entity.
|
|
89
|
+
*/
|
|
90
|
+
export function enclosedByRepositoryAncestor(record, lookup) {
|
|
91
|
+
const seen = new Set([record.uuid]);
|
|
92
|
+
let parentUUID = record.parentUUID;
|
|
93
|
+
while (parentUUID !== null && parentUUID !== undefined) {
|
|
94
|
+
if (seen.has(parentUUID))
|
|
95
|
+
throw new Error(`cloud entity ${record.uuid} has a cyclic parent chain`);
|
|
96
|
+
seen.add(parentUUID);
|
|
97
|
+
const parent = lookup(parentUUID);
|
|
98
|
+
if (!parent)
|
|
99
|
+
return false;
|
|
100
|
+
if (parent.type === 'repo.git')
|
|
101
|
+
return true;
|
|
102
|
+
parentUUID = parent.parentUUID;
|
|
103
|
+
}
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
/** Normalize records into the one canonical snapshot: asserted, sorted by
|
|
107
|
+
* uuid, duplicates refused. */
|
|
108
|
+
export function snapshotFromRecords(records) {
|
|
109
|
+
const normalized = records.map(assertRecord)
|
|
110
|
+
.sort((left, right) => (left.uuid < right.uuid ? -1 : left.uuid > right.uuid ? 1 : 0));
|
|
111
|
+
if (new Set(normalized.map((record) => record.uuid)).size !== normalized.length) {
|
|
112
|
+
throw new Error('cloud entity snapshot has duplicate UUIDs');
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
schemaVersion: ENTITY_CLOUD_SCHEMA_VERSION,
|
|
116
|
+
kind: 'amalgm-entity-registry',
|
|
117
|
+
records: normalized,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
/** Parse snapshot bytes (or their UTF-8 text) back into the canonical form. */
|
|
121
|
+
export function parseSnapshot(bytes) {
|
|
122
|
+
let snapshot;
|
|
123
|
+
try {
|
|
124
|
+
snapshot = JSON.parse(typeof bytes === 'string' ? bytes : utf8Decode(bytes));
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
throw new Error('cloud entity snapshot is not JSON');
|
|
128
|
+
}
|
|
129
|
+
if (snapshot?.schemaVersion !== ENTITY_CLOUD_SCHEMA_VERSION
|
|
130
|
+
|| snapshot?.kind !== 'amalgm-entity-registry'
|
|
131
|
+
|| !Array.isArray(snapshot.records)) {
|
|
132
|
+
throw new Error('cloud entity snapshot has an unsupported shape');
|
|
133
|
+
}
|
|
134
|
+
return snapshotFromRecords(snapshot.records);
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=cloud.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloud.js","sourceRoot":"","sources":["../../src/entities/cloud.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* entities/ — the Register/Record pure cores: the entity model's laws
|
|
3
|
+
* (engine docs/entity-model.md — two axioms, the six-field record) as
|
|
4
|
+
* portable functions. Store reads arrive through `EntityReadPort`, hashing
|
|
5
|
+
* through `Sha256Hex`; nothing here touches SQLite, node:crypto, or a
|
|
6
|
+
* filesystem. Hash formulas and id derivations are byte-for-byte the
|
|
7
|
+
* engine's, so records interoperate across the cloud boundary.
|
|
8
|
+
*
|
|
9
|
+
* - types.ts the alphabet, the six fields, UUID shape, injected ports
|
|
10
|
+
* - bytes.ts portable byte codecs (utf8, base64, base64url, hex)
|
|
11
|
+
* - rules.ts version formula, naming, lifecycle inheritance,
|
|
12
|
+
* slot/container laws, record builders
|
|
13
|
+
* - moves.ts batch move validation: permutations, acyclicity, adoption
|
|
14
|
+
* - cloud.ts entity-cloud snapshot codec + the repo travel law
|
|
15
|
+
* - repo-states.ts Card + Checkpoint state codec and id derivations
|
|
16
|
+
*/
|
|
17
|
+
export * from './types.js';
|
|
18
|
+
export * from './bytes.js';
|
|
19
|
+
export * from './rules.js';
|
|
20
|
+
export * from './moves.js';
|
|
21
|
+
export * from './cloud.js';
|
|
22
|
+
export * from './repo-states.js';
|
|
23
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/entities/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* entities/ — the Register/Record pure cores: the entity model's laws
|
|
3
|
+
* (engine docs/entity-model.md — two axioms, the six-field record) as
|
|
4
|
+
* portable functions. Store reads arrive through `EntityReadPort`, hashing
|
|
5
|
+
* through `Sha256Hex`; nothing here touches SQLite, node:crypto, or a
|
|
6
|
+
* filesystem. Hash formulas and id derivations are byte-for-byte the
|
|
7
|
+
* engine's, so records interoperate across the cloud boundary.
|
|
8
|
+
*
|
|
9
|
+
* - types.ts the alphabet, the six fields, UUID shape, injected ports
|
|
10
|
+
* - bytes.ts portable byte codecs (utf8, base64, base64url, hex)
|
|
11
|
+
* - rules.ts version formula, naming, lifecycle inheritance,
|
|
12
|
+
* slot/container laws, record builders
|
|
13
|
+
* - moves.ts batch move validation: permutations, acyclicity, adoption
|
|
14
|
+
* - cloud.ts entity-cloud snapshot codec + the repo travel law
|
|
15
|
+
* - repo-states.ts Card + Checkpoint state codec and id derivations
|
|
16
|
+
*/
|
|
17
|
+
export * from './types.js';
|
|
18
|
+
export * from './bytes.js';
|
|
19
|
+
export * from './rules.js';
|
|
20
|
+
export * from './moves.js';
|
|
21
|
+
export * from './cloud.js';
|
|
22
|
+
export * from './repo-states.js';
|
|
23
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/entities/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC"}
|