@a-company/gnomon 0.0.0-stage → 8.0.2
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 +126 -2
- package/dist/agent.d.ts +28 -0
- package/dist/agent.js +45708 -0
- package/dist/build-id.json +1 -0
- package/dist/cli/gnomon.js +53946 -0
- package/dist/cli/gnomond.js +47744 -0
- package/dist/gnomon-local/cli.js +897 -0
- package/dist/index.d.ts +3477 -0
- package/dist/index.js +13698 -0
- package/dist/loops.d.ts +440 -0
- package/dist/loops.js +4706 -0
- package/dist/signer-CQ3Bpe7G.d.ts +158 -0
- package/dist/transport/gnomon-web.js +688 -0
- package/gnomon-mods/.purpose +143 -0
- package/gnomon-mods/constellation/README.md +27 -0
- package/gnomon-mods/constellation/fixtures/map-the-idea.golden.json +19 -0
- package/gnomon-mods/constellation/fixtures/map-the-idea.json +3 -0
- package/gnomon-mods/constellation/fixtures/summarize-the-session.golden.json +20 -0
- package/gnomon-mods/constellation/fixtures/summarize-the-session.json +3 -0
- package/gnomon-mods/constellation/fixtures/two-blocks.golden.json +4 -0
- package/gnomon-mods/constellation/fixtures/two-blocks.json +3 -0
- package/gnomon-mods/constellation/gnomon-manifest.json +68 -0
- package/gnomon-mods/constellation/skills/constellation-desk/SKILL.md +35 -0
- package/gnomon-mods/ledger/README.md +10 -0
- package/gnomon-mods/ledger/fixtures/breaker.golden.json +28 -0
- package/gnomon-mods/ledger/fixtures/breaker.json +80 -0
- package/gnomon-mods/ledger/fixtures/compacted.golden.json +42 -0
- package/gnomon-mods/ledger/fixtures/compacted.json +103 -0
- package/gnomon-mods/ledger/fixtures/over-budget.golden.json +24 -0
- package/gnomon-mods/ledger/fixtures/over-budget.json +86 -0
- package/gnomon-mods/ledger/fixtures/strip-reduced.golden.json +23 -0
- package/gnomon-mods/ledger/fixtures/strip-reduced.json +76 -0
- package/gnomon-mods/ledger/fixtures/strip.golden.json +18 -0
- package/gnomon-mods/ledger/fixtures/strip.json +68 -0
- package/gnomon-mods/ledger/gnomon-manifest.json +16 -0
- package/gnomon-mods/ledger/index.mjs +77 -0
- package/gnomon-mods/ledger/model.mjs +237 -0
- package/gnomon-mods/neurons/README.md +31 -0
- package/gnomon-mods/neurons/fixtures/capture-a-decision.golden.json +20 -0
- package/gnomon-mods/neurons/fixtures/capture-a-decision.json +3 -0
- package/gnomon-mods/neurons/fixtures/capture-a-learning.golden.json +19 -0
- package/gnomon-mods/neurons/fixtures/capture-a-learning.json +3 -0
- package/gnomon-mods/neurons/fixtures/search-the-brain.golden.json +19 -0
- package/gnomon-mods/neurons/fixtures/search-the-brain.json +3 -0
- package/gnomon-mods/neurons/fixtures/undeclared-kind.golden.json +9 -0
- package/gnomon-mods/neurons/fixtures/undeclared-kind.json +3 -0
- package/gnomon-mods/neurons/gnomon-manifest.json +87 -0
- package/gnomon-mods/neurons/skills/neurons-desk/SKILL.md +44 -0
- package/gnomon-mods/paradigm-context/README.md +9 -0
- package/gnomon-mods/paradigm-context/fixtures/empty.golden.json +28 -0
- package/gnomon-mods/paradigm-context/fixtures/empty.json +48 -0
- package/gnomon-mods/paradigm-context/fixtures/full-dark.golden.json +497 -0
- package/gnomon-mods/paradigm-context/fixtures/full-dark.json +134 -0
- package/gnomon-mods/paradigm-context/fixtures/full.golden.json +497 -0
- package/gnomon-mods/paradigm-context/fixtures/full.json +134 -0
- package/gnomon-mods/paradigm-context/fixtures/stale.golden.json +205 -0
- package/gnomon-mods/paradigm-context/fixtures/stale.json +69 -0
- package/gnomon-mods/paradigm-context/fixtures/unfocused.golden.json +28 -0
- package/gnomon-mods/paradigm-context/fixtures/unfocused.json +14 -0
- package/gnomon-mods/paradigm-context/gnomon-manifest.json +15 -0
- package/gnomon-mods/paradigm-context/index.mjs +64 -0
- package/gnomon-mods/paradigm-context/model.mjs +137 -0
- package/gnomon-mods/workshop/README.md +12 -0
- package/gnomon-mods/workshop/fixtures/strip-reduced.golden.json +56 -0
- package/gnomon-mods/workshop/fixtures/strip-reduced.json +16 -0
- package/gnomon-mods/workshop/fixtures/strip.golden.json +56 -0
- package/gnomon-mods/workshop/fixtures/strip.json +16 -0
- package/gnomon-mods/workshop/gnomon-manifest.json +14 -0
- package/gnomon-mods/workshop/index.mjs +73 -0
- package/gnomon-mods/workshop/model.mjs +152 -0
- package/package.json +80 -4
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { KeyObject } from 'node:crypto';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @symbol #kernel-log
|
|
5
|
+
*
|
|
6
|
+
* #kernel-log (spec §3.1 key classes + signature domains, §3.2 "Signatures and
|
|
7
|
+
* anchors") — the `Signer` seam and the key ring the verifier uses.
|
|
8
|
+
*
|
|
9
|
+
* THE SEAM. Every signature the log writes goes through `Signer.sign(domain,
|
|
10
|
+
* message)`. The signer, not the caller, prepends the domain, so a signature
|
|
11
|
+
* made for one purpose can never verify for another (domain separation):
|
|
12
|
+
*
|
|
13
|
+
* preimage = utf8(<domain> + "\n" + <message>)
|
|
14
|
+
*
|
|
15
|
+
* with the §3.1 domains `gnomon:event-sig:v1`, `gnomon:row-sig:v1`,
|
|
16
|
+
* `gnomon:approve:v1`, `gnomon:approve-voice:v1`, `gnomon:auth:v1` and
|
|
17
|
+
* `gnomon:brief:v1`. For an event, `message` is the event's tagged hash
|
|
18
|
+
* (`sha256:<hex>`), so the signature commits to the whole envelope.
|
|
19
|
+
*
|
|
20
|
+
* Each key class may sign only its own domains (§3.1): the kernel key signs
|
|
21
|
+
* events, `hello` serverSig (`gnomon:auth-server:v2`, M1.4 — never the client
|
|
22
|
+
* `gnomon:auth:v1` domain, so the kernel is no signing oracle for client
|
|
23
|
+
* transcripts) and briefs; the root key signs rows
|
|
24
|
+
* (registry, grants, config, install); the approvals key signs decisions.
|
|
25
|
+
*
|
|
26
|
+
* PR-4 ships ONE implementation: `SoftwareEd25519Signer`, the kernel key held
|
|
27
|
+
* in kernel memory. In production the key material comes from the OS keystore
|
|
28
|
+
* item `gnomon-kernel-key` via the signed helper (§3.1); until probes P04
|
|
29
|
+
* (Secure Enclave / helper) and P02 land, a caller hands the PEM in. The root
|
|
30
|
+
* and approvals keys are HARDWARE P-256 and never software (§3.1 failure
|
|
31
|
+
* modes: "never a software fallback, never a file") — their signers plug in
|
|
32
|
+
* behind this same interface after P04/P02. The key ring already VERIFIES
|
|
33
|
+
* `gkey-p256:v1` signatures (ECDSA P-256 / SHA-256, IEEE-P1363 encoding) so
|
|
34
|
+
* those rows verify the day they appear.
|
|
35
|
+
*
|
|
36
|
+
* The interface is synchronous because the kernel key lives in kernel memory
|
|
37
|
+
* (§3.1 "loaded into kernel memory at daemon start") and append runs inside a
|
|
38
|
+
* write transaction. A hardware signer is asynchronous (helper XPC); it will
|
|
39
|
+
* get an async append path that serializes on the chain tip — deferred with
|
|
40
|
+
* the hardware signers.
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
/** The §3.1 signature domains (the prefix before the first `\n`). */
|
|
44
|
+
declare const SIGNATURE_DOMAINS: {
|
|
45
|
+
readonly event: "gnomon:event-sig:v1";
|
|
46
|
+
readonly row: "gnomon:row-sig:v1";
|
|
47
|
+
readonly approve: "gnomon:approve:v1";
|
|
48
|
+
readonly approveVoice: "gnomon:approve-voice:v1";
|
|
49
|
+
/** The three auth domains come FROM the contracts constants (P8-D93 round 3): one definition, in clientApiId. */
|
|
50
|
+
readonly auth: "gnomon:auth:v1";
|
|
51
|
+
/** #socket serverSig (§4.9): `gnomon:auth-server:v2\n` + contracts authServerMessage (nonce, clientNonce, endpointPath, negotiated hello; v2 since P8-D93), kernel key only. */
|
|
52
|
+
readonly authServer: "gnomon:auth-server:v2";
|
|
53
|
+
/** Read-token proof of possession (§4.9, P8-D89a): the token's own Ed25519 key only. */
|
|
54
|
+
readonly authToken: "gnomon:auth-token:v1";
|
|
55
|
+
readonly brief: "gnomon:brief:v1";
|
|
56
|
+
/**
|
|
57
|
+
* #approval-broker (M1.6): the kernel key signs `card.actions[]` and the
|
|
58
|
+
* presence-prompt record (§3.1 kernel key "Signs:"). The spec names no
|
|
59
|
+
* domain string for either; these two are kernel-internal (not in
|
|
60
|
+
* clientApiId) and keep both apart from event signatures.
|
|
61
|
+
*/
|
|
62
|
+
readonly cardAction: "gnomon:card-action:v1";
|
|
63
|
+
readonly presencePrompt: "gnomon:presence-prompt:v1";
|
|
64
|
+
/** #budget-fuse (M1.6): the kernel key signs every permit:v1 (§4.8 `sig`); kernel-internal domain. */
|
|
65
|
+
readonly permit: "gnomon:permit:v1";
|
|
66
|
+
/**
|
|
67
|
+
* #identity (M1.3): a hardware presence attestation — the approvals key
|
|
68
|
+
* (Secure Enclave, behind the signed helper; never the root, round 2 M1) signs a kernel challenge
|
|
69
|
+
* `<purpose>\n<bindingDigest>\n<connId>\n<challenge>` after the helper's
|
|
70
|
+
* presence prompt; the presence module mints a PresenceToken only on a
|
|
71
|
+
* verified one. Kernel-internal (not in clientApiId).
|
|
72
|
+
*/
|
|
73
|
+
readonly presence: "gnomon:presence:v1";
|
|
74
|
+
};
|
|
75
|
+
type SignatureDomain = keyof typeof SIGNATURE_DOMAINS;
|
|
76
|
+
/** §3.1 key classes that sign (the link key never signs; X25519, Noise only). */
|
|
77
|
+
type KeyClass = 'kernel' | 'root' | 'approvals' | 'device' | 'agent' | 'readToken';
|
|
78
|
+
/** Which domains each key class may sign (§3.1 "Signs:" per class). */
|
|
79
|
+
declare const DOMAINS_BY_KEY_CLASS: Readonly<Record<KeyClass, readonly SignatureDomain[]>>;
|
|
80
|
+
type KeyCustody = 'software' | 'hardware';
|
|
81
|
+
interface Signer {
|
|
82
|
+
/** `gkey:v1:<sha256(normalized spki PEM)>` (Ed25519) or `gkey-p256:v1:…`. */
|
|
83
|
+
readonly keyId: string;
|
|
84
|
+
readonly keyClass: KeyClass;
|
|
85
|
+
readonly custody: KeyCustody;
|
|
86
|
+
/** Sign `domain + "\n" + message`; throws if this key class may not sign the domain. */
|
|
87
|
+
sign(domain: SignatureDomain, message: string): Uint8Array;
|
|
88
|
+
}
|
|
89
|
+
/** The exact bytes a signature covers. */
|
|
90
|
+
declare function signaturePreimage(domain: SignatureDomain, message: string): Buffer;
|
|
91
|
+
/** The approve-domain message (§3.1): approver in the preimage (Q5). */
|
|
92
|
+
declare function approveMessage(f: {
|
|
93
|
+
cardId: string;
|
|
94
|
+
decision: string;
|
|
95
|
+
cardContentHash: string;
|
|
96
|
+
approverPrincipalId: string;
|
|
97
|
+
}): string;
|
|
98
|
+
/**
|
|
99
|
+
* #approval-broker decisionSig v2 (P8-D98, TD-2026-10-19-648, slice A2). The v2 layout (contracts
|
|
100
|
+
* decisionMessageV2) adds the answer digest, so a typed `answer{text}` binds the text the human approved:
|
|
101
|
+
* gnomon:decision:v2 \n cardId \n decision \n cardContentHash \n approverPrincipalId \n answerDigest
|
|
102
|
+
* It is used ONLY for the DECISION_SIG_V2_DECISIONS (`answer`); every other decision keeps the v1
|
|
103
|
+
* approveMessage. The domain stays `gnomon:approve:v1`: the version lives in the message's first line.
|
|
104
|
+
*/
|
|
105
|
+
declare function usesDecisionV2(decision: string): boolean;
|
|
106
|
+
/** sha256:<hex> of the UTF-8 answer text (the same bytes approval.decide records as noteHash). */
|
|
107
|
+
declare function answerDigest(text: string): string;
|
|
108
|
+
/**
|
|
109
|
+
* The decisionSig message for a decision: v2 for `answer` (answerDigest REQUIRED; a missing one throws,
|
|
110
|
+
* never a silent v1), v1 approveMessage otherwise (an answerDigest on a v1 decision throws: no ambiguity).
|
|
111
|
+
*/
|
|
112
|
+
declare function decisionMessage(f: {
|
|
113
|
+
cardId: string;
|
|
114
|
+
decision: string;
|
|
115
|
+
cardContentHash: string;
|
|
116
|
+
approverPrincipalId: string;
|
|
117
|
+
answerDigest?: string;
|
|
118
|
+
/** TD-2026-10-20-294: a prefix-scoped `always` signs v2 with the scope digest as its last line */
|
|
119
|
+
scopeDigest?: string;
|
|
120
|
+
}): string;
|
|
121
|
+
/** keyId for an Ed25519 public key: `gkey:v1:` + sha256(normalized spki PEM). */
|
|
122
|
+
declare function ed25519KeyId(publicKeyPem: string): string;
|
|
123
|
+
/** keyId for a P-256 public key: `gkey-p256:v1:` + sha256(spki DER). */
|
|
124
|
+
declare function p256KeyId(publicKey: KeyObject): string;
|
|
125
|
+
declare class SignerDomainError extends Error {
|
|
126
|
+
constructor(keyClass: KeyClass, domain: SignatureDomain);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* The software Ed25519 signer — the kernel key held in memory (PR-4). Also the
|
|
130
|
+
* shape device and agent keys take (they are Ed25519 files, §3.1). Refuses to
|
|
131
|
+
* be constructed as a root or approvals key: those are hardware-only.
|
|
132
|
+
*/
|
|
133
|
+
declare class SoftwareEd25519Signer implements Signer {
|
|
134
|
+
#private;
|
|
135
|
+
readonly keyId: string;
|
|
136
|
+
readonly keyClass: KeyClass;
|
|
137
|
+
readonly custody: "software";
|
|
138
|
+
readonly publicKeyPem: string;
|
|
139
|
+
constructor(privateKeyPem: string, keyClass?: KeyClass);
|
|
140
|
+
/** A fresh in-memory kernel key (tests; production loads from the keystore). */
|
|
141
|
+
static generate(keyClass?: KeyClass): SoftwareEd25519Signer;
|
|
142
|
+
sign(domain: SignatureDomain, message: string): Uint8Array;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Public keys by keyId, for verification. M1.3 (#identity) fills it from the
|
|
146
|
+
* root-signed registry; PR-4 callers add keys directly. Never throws on
|
|
147
|
+
* malformed input: a bad signature or unknown key is simply `false`/`unknown`.
|
|
148
|
+
*/
|
|
149
|
+
declare class KeyRing {
|
|
150
|
+
#private;
|
|
151
|
+
addEd25519(publicKeyPem: string): string;
|
|
152
|
+
addP256(publicKey: KeyObject | string): string;
|
|
153
|
+
has(keyId: string): boolean;
|
|
154
|
+
verify(keyId: string, domain: SignatureDomain, message: string, sig: Uint8Array): 'ok' | 'bad' | 'unknown-key';
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export { DOMAINS_BY_KEY_CLASS as D, KeyRing as K, SIGNATURE_DOMAINS as c, SignerDomainError as e, SoftwareEd25519Signer as f, answerDigest as g, approveMessage as h, decisionMessage as i, ed25519KeyId as j, p256KeyId as p, signaturePreimage as s, usesDecisionV2 as u };
|
|
158
|
+
export type { Signer as S, KeyClass as a, KeyCustody as b, SignatureDomain as d };
|