@viewportai/daemon 0.5.2 → 0.6.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.
Files changed (109) hide show
  1. package/dist/cli/commands.d.ts +1 -0
  2. package/dist/cli/commands.d.ts.map +1 -1
  3. package/dist/cli/commands.js +1 -0
  4. package/dist/cli/commands.js.map +1 -1
  5. package/dist/cli/context-access-command.d.ts +0 -6
  6. package/dist/cli/context-access-command.d.ts.map +1 -1
  7. package/dist/cli/context-access-command.js +1 -71
  8. package/dist/cli/context-access-command.js.map +1 -1
  9. package/dist/cli/context-command.d.ts.map +1 -1
  10. package/dist/cli/context-command.js +593 -27
  11. package/dist/cli/context-command.js.map +1 -1
  12. package/dist/cli/context-sync-target.d.ts +2 -1
  13. package/dist/cli/context-sync-target.d.ts.map +1 -1
  14. package/dist/cli/context-sync-target.js +28 -0
  15. package/dist/cli/context-sync-target.js.map +1 -1
  16. package/dist/cli/context-vault-metadata-command.d.ts.map +1 -1
  17. package/dist/cli/context-vault-metadata-command.js +6 -1
  18. package/dist/cli/context-vault-metadata-command.js.map +1 -1
  19. package/dist/cli/lifecycle-commands.d.ts.map +1 -1
  20. package/dist/cli/lifecycle-commands.js +6 -6
  21. package/dist/cli/lifecycle-commands.js.map +1 -1
  22. package/dist/cli/unlock-command.d.ts +2 -0
  23. package/dist/cli/unlock-command.d.ts.map +1 -0
  24. package/dist/cli/unlock-command.js +35 -0
  25. package/dist/cli/unlock-command.js.map +1 -0
  26. package/dist/context/local-edge-store.d.ts +23 -1
  27. package/dist/context/local-edge-store.d.ts.map +1 -1
  28. package/dist/context/local-edge-store.js +51 -0
  29. package/dist/context/local-edge-store.js.map +1 -1
  30. package/dist/context/local-edge-sync.d.ts +63 -0
  31. package/dist/context/local-edge-sync.d.ts.map +1 -1
  32. package/dist/context/local-edge-sync.js +464 -4
  33. package/dist/context/local-edge-sync.js.map +1 -1
  34. package/dist/context/local-edge-types.d.ts +21 -0
  35. package/dist/context/local-edge-types.d.ts.map +1 -1
  36. package/dist/hooks/platform-plan-sync.d.ts +4 -1
  37. package/dist/hooks/platform-plan-sync.d.ts.map +1 -1
  38. package/dist/hooks/platform-plan-sync.js +20 -5
  39. package/dist/hooks/platform-plan-sync.js.map +1 -1
  40. package/dist/hooks/trusted-edge-plan-artifacts.d.ts +117 -0
  41. package/dist/hooks/trusted-edge-plan-artifacts.d.ts.map +1 -0
  42. package/dist/hooks/trusted-edge-plan-artifacts.js +371 -0
  43. package/dist/hooks/trusted-edge-plan-artifacts.js.map +1 -0
  44. package/dist/index.d.ts +1 -0
  45. package/dist/index.d.ts.map +1 -1
  46. package/dist/index.js +3 -1
  47. package/dist/index.js.map +1 -1
  48. package/dist/relay/bridge-token-issuer.d.ts +1 -0
  49. package/dist/relay/bridge-token-issuer.d.ts.map +1 -1
  50. package/dist/relay/bridge-token-issuer.js +1 -1
  51. package/dist/relay/bridge-token-issuer.js.map +1 -1
  52. package/dist/security/epoch-enrollment.d.ts +48 -0
  53. package/dist/security/epoch-enrollment.d.ts.map +1 -0
  54. package/dist/security/epoch-enrollment.js +290 -0
  55. package/dist/security/epoch-enrollment.js.map +1 -0
  56. package/dist/security/epoch-protocol.d.ts +181 -0
  57. package/dist/security/epoch-protocol.d.ts.map +1 -0
  58. package/dist/security/epoch-protocol.js +285 -0
  59. package/dist/security/epoch-protocol.js.map +1 -0
  60. package/dist/security/epoch-public-pins.d.ts +19 -0
  61. package/dist/security/epoch-public-pins.d.ts.map +1 -0
  62. package/dist/security/epoch-public-pins.js +129 -0
  63. package/dist/security/epoch-public-pins.js.map +1 -0
  64. package/dist/security/epoch-recovery.d.ts +56 -0
  65. package/dist/security/epoch-recovery.d.ts.map +1 -0
  66. package/dist/security/epoch-recovery.js +314 -0
  67. package/dist/security/epoch-recovery.js.map +1 -0
  68. package/dist/security/epoch-store.d.ts +111 -0
  69. package/dist/security/epoch-store.d.ts.map +1 -0
  70. package/dist/security/epoch-store.js +224 -0
  71. package/dist/security/epoch-store.js.map +1 -0
  72. package/dist/security/epoch-sync.d.ts +47 -0
  73. package/dist/security/epoch-sync.d.ts.map +1 -0
  74. package/dist/security/epoch-sync.js +371 -0
  75. package/dist/security/epoch-sync.js.map +1 -0
  76. package/dist/security/team-epoch-grants.d.ts +28 -0
  77. package/dist/security/team-epoch-grants.d.ts.map +1 -0
  78. package/dist/security/team-epoch-grants.js +256 -0
  79. package/dist/security/team-epoch-grants.js.map +1 -0
  80. package/dist/server/context-preview-service.d.ts +26 -0
  81. package/dist/server/context-preview-service.d.ts.map +1 -0
  82. package/dist/server/context-preview-service.js +71 -0
  83. package/dist/server/context-preview-service.js.map +1 -0
  84. package/dist/server/http-context-routes.d.ts +2 -1
  85. package/dist/server/http-context-routes.d.ts.map +1 -1
  86. package/dist/server/http-context-routes.js +65 -30
  87. package/dist/server/http-context-routes.js.map +1 -1
  88. package/dist/server/http-server.js +1 -1
  89. package/dist/server/http-server.js.map +1 -1
  90. package/dist/server/rate-limiter.d.ts.map +1 -1
  91. package/dist/server/rate-limiter.js +6 -1
  92. package/dist/server/rate-limiter.js.map +1 -1
  93. package/dist/server/trusted-edge-command-capability.d.ts +14 -0
  94. package/dist/server/trusted-edge-command-capability.d.ts.map +1 -0
  95. package/dist/server/trusted-edge-command-capability.js +114 -0
  96. package/dist/server/trusted-edge-command-capability.js.map +1 -0
  97. package/dist/server/ws-command-handlers.d.ts.map +1 -1
  98. package/dist/server/ws-command-handlers.js +231 -27
  99. package/dist/server/ws-command-handlers.js.map +1 -1
  100. package/dist/server/ws-protocol.d.ts +419 -5
  101. package/dist/server/ws-protocol.d.ts.map +1 -1
  102. package/dist/server/ws-protocol.js +141 -4
  103. package/dist/server/ws-protocol.js.map +1 -1
  104. package/docs/protocol-matrix.json +93 -5
  105. package/node_modules/@viewportai/context-engine/src/repo/materializer.js +20 -5
  106. package/node_modules/@viewportai/context-engine/src/repo/membership.js +15 -0
  107. package/node_modules/@viewportai/context-engine/src/repo/sync.js +4 -4
  108. package/node_modules/@viewportai/context-engine/src/repo/vault.js +8 -3
  109. package/package.json +1 -1
@@ -0,0 +1,285 @@
1
+ import crypto from 'node:crypto';
2
+ export const USER_EPOCH_SCHEMA = 'viewport.user_crypto_epoch/v1';
3
+ export const TEAM_EPOCH_SCHEMA = 'viewport.team_crypto_epoch/v1';
4
+ export const DEVICE_ENROLLMENT_SCHEMA = 'viewport.device_enrollment/v1';
5
+ export const RESOURCE_GRANT_SCHEMA = 'viewport.resource_key_grant/v1';
6
+ export const WRAPPED_KEY_ENVELOPE_SCHEMA = 'viewport.wrapped_key_envelope/v1';
7
+ export const TRUSTED_EDGE_CRYPTO_PROTOCOL_HEADER = 'X-Viewport-Crypto-Protocol';
8
+ export const TRUSTED_EDGE_CRYPTO_PROTOCOL_VERSION = 'viewport.trusted_edge_crypto/v2';
9
+ const PRIVATE_JWK_FIELDS = new Set([
10
+ 'd',
11
+ 'p',
12
+ 'q',
13
+ 'dp',
14
+ 'dq',
15
+ 'qi',
16
+ 'oth',
17
+ 'k',
18
+ 'x5c_private',
19
+ 'hpkePrivateKey',
20
+ 'privateKey',
21
+ 'secretKey',
22
+ ]);
23
+ export function canonicalJson(value) {
24
+ return JSON.stringify(canonicalize(value));
25
+ }
26
+ export function sha256Base64Url(value) {
27
+ return crypto.createHash('sha256').update(value).digest('base64url');
28
+ }
29
+ export function fingerprintPayload(value) {
30
+ return `sha256:${sha256Base64Url(canonicalJson(value))}`;
31
+ }
32
+ export function epochFingerprint(epoch) {
33
+ return fingerprintPayload({
34
+ schema: epoch.schema,
35
+ workspaceId: epoch.workspaceId,
36
+ subjectType: epoch.subjectType,
37
+ subjectId: epoch.subjectId,
38
+ epoch: epoch.epoch,
39
+ encryptionPublicKeyJwk: epoch.encryptionPublicKeyJwk,
40
+ signingPublicKeyJwk: epoch.signingPublicKeyJwk,
41
+ previousEpochFingerprint: epoch.previousEpochFingerprint ?? null,
42
+ });
43
+ }
44
+ export function deviceEnrollmentFingerprint(request) {
45
+ assertNoPrivateKeyMaterial(request.encryptionPublicKeyJwk);
46
+ assertNoPrivateKeyMaterial(request.signingPublicKeyJwk);
47
+ return fingerprintPayload({
48
+ schema: request.schema,
49
+ workspaceId: request.workspaceId,
50
+ deviceId: request.deviceId,
51
+ deviceLabel: request.deviceLabel,
52
+ encryptionPublicKeyJwk: request.encryptionPublicKeyJwk,
53
+ signingPublicKeyJwk: request.signingPublicKeyJwk,
54
+ nonce: request.nonce,
55
+ });
56
+ }
57
+ export function signDeviceEnrollmentRequest(input) {
58
+ const key = crypto.createPrivateKey({
59
+ key: input.signingPrivateKeyJwk,
60
+ format: 'jwk',
61
+ });
62
+ return {
63
+ payload: input.payload,
64
+ signature: crypto
65
+ .sign(null, Buffer.from(canonicalJson(input.payload)), key)
66
+ .toString('base64url'),
67
+ };
68
+ }
69
+ export function userEpochDeviceMaterializationPayload(input) {
70
+ return {
71
+ schema: 'viewport.user_epoch_device_materialization/v1',
72
+ workspaceId: input.workspaceId,
73
+ userId: input.userId,
74
+ enrollmentId: input.enrollmentId,
75
+ grantId: input.grantId,
76
+ userCryptoEpochId: input.userCryptoEpochId,
77
+ userEpochFingerprint: input.userEpochFingerprint,
78
+ recipientFingerprint: input.recipientFingerprint,
79
+ };
80
+ }
81
+ export function signUserEpochDeviceMaterialization(input) {
82
+ const key = crypto.createPrivateKey({
83
+ key: input.signingPrivateKeyJwk,
84
+ format: 'jwk',
85
+ });
86
+ return {
87
+ payload: input.payload,
88
+ signature: crypto
89
+ .sign(null, Buffer.from(canonicalJson(input.payload)), key)
90
+ .toString('base64url'),
91
+ signedByUserEpochFingerprint: input.signedByUserEpochFingerprint,
92
+ };
93
+ }
94
+ export function teamEpochMemberMaterializationPayload(input) {
95
+ return {
96
+ schema: 'viewport.team_epoch_member_materialization/v1',
97
+ workspaceId: input.workspaceId,
98
+ grantId: input.grantId,
99
+ teamCryptoEpochId: input.teamCryptoEpochId,
100
+ teamEpochFingerprint: input.teamEpochFingerprint,
101
+ recipientUserCryptoEpochId: input.recipientUserCryptoEpochId,
102
+ recipientUserEpochFingerprint: input.recipientUserEpochFingerprint,
103
+ };
104
+ }
105
+ export function signTeamEpochMemberMaterialization(input) {
106
+ const key = crypto.createPrivateKey({
107
+ key: input.signingPrivateKeyJwk,
108
+ format: 'jwk',
109
+ });
110
+ return {
111
+ payload: input.payload,
112
+ signature: crypto
113
+ .sign(null, Buffer.from(canonicalJson(input.payload)), key)
114
+ .toString('base64url'),
115
+ signedByTeamEpochFingerprint: input.signedByTeamEpochFingerprint,
116
+ };
117
+ }
118
+ export function contextGrantMaterializationPayload(input) {
119
+ return {
120
+ schema: 'viewport.context_vault_grant_materialization/v1',
121
+ workspaceId: input.workspaceId,
122
+ contextResourceId: input.contextResourceId,
123
+ grantEventId: input.grantEventId,
124
+ recipientName: input.recipientName,
125
+ keyEpoch: input.keyEpoch,
126
+ };
127
+ }
128
+ export function signContextGrantMaterialization(input) {
129
+ const key = crypto.createPrivateKey({
130
+ key: input.signingPrivateKeyJwk,
131
+ format: 'jwk',
132
+ });
133
+ return {
134
+ payload: input.payload,
135
+ signature: crypto
136
+ .sign(null, Buffer.from(canonicalJson(input.payload)), key)
137
+ .toString('base64url'),
138
+ signedByEpochFingerprint: input.signedByEpochFingerprint,
139
+ };
140
+ }
141
+ export function epochTransitionPayload(input) {
142
+ if (input.from.workspaceId !== input.to.workspaceId) {
143
+ throw new Error('Epoch transition workspace mismatch.');
144
+ }
145
+ if (input.from.subjectType !== input.to.subjectType ||
146
+ input.from.subjectId !== input.to.subjectId) {
147
+ throw new Error('Epoch transition subject mismatch.');
148
+ }
149
+ if (input.to.epoch !== input.from.epoch + 1) {
150
+ throw new Error('Epoch transition must advance by exactly one epoch.');
151
+ }
152
+ return {
153
+ schema: 'viewport.epoch_transition/v1',
154
+ workspaceId: input.from.workspaceId,
155
+ subjectType: input.from.subjectType,
156
+ subjectId: input.from.subjectId,
157
+ fromEpoch: input.from.epoch,
158
+ fromEpochFingerprint: epochFingerprint(input.from),
159
+ toEpoch: input.to.epoch,
160
+ toEpochFingerprint: epochFingerprint(input.to),
161
+ reason: input.reason,
162
+ createdAt: input.createdAt,
163
+ };
164
+ }
165
+ export function signEpochTransition(input) {
166
+ const key = crypto.createPrivateKey({
167
+ key: input.signingPrivateKeyJwk,
168
+ format: 'jwk',
169
+ });
170
+ const signature = crypto
171
+ .sign(null, Buffer.from(canonicalJson(input.payload)), key)
172
+ .toString('base64url');
173
+ return {
174
+ payload: input.payload,
175
+ signature,
176
+ signedByEpochFingerprint: input.signedByEpochFingerprint,
177
+ };
178
+ }
179
+ export function verifyEpochTransition(input) {
180
+ if (input.signed.signedByEpochFingerprint !== input.expectedFromEpochFingerprint)
181
+ return false;
182
+ if (input.signed.payload.fromEpochFingerprint !== input.expectedFromEpochFingerprint)
183
+ return false;
184
+ if (input.signed.payload.toEpochFingerprint !== input.expectedToEpochFingerprint)
185
+ return false;
186
+ const key = crypto.createPublicKey({
187
+ key: input.signingPublicKeyJwk,
188
+ format: 'jwk',
189
+ });
190
+ return crypto.verify(null, Buffer.from(canonicalJson(input.signed.payload)), key, Buffer.from(input.signed.signature, 'base64url'));
191
+ }
192
+ export function wrapJsonForX25519Recipient(input) {
193
+ assertNoPrivateKeyMaterial(input.recipientPublicKeyJwk);
194
+ const ephemeral = crypto.generateKeyPairSync('x25519');
195
+ const recipientPublicKey = crypto.createPublicKey({
196
+ key: input.recipientPublicKeyJwk,
197
+ format: 'jwk',
198
+ });
199
+ const sharedSecret = crypto.diffieHellman({
200
+ privateKey: ephemeral.privateKey,
201
+ publicKey: recipientPublicKey,
202
+ });
203
+ const aad = Buffer.from(canonicalJson(input.aad));
204
+ const iv = crypto.randomBytes(12);
205
+ const cipher = crypto.createCipheriv('aes-256-gcm', deriveWrapKey(sharedSecret), iv);
206
+ cipher.setAAD(aad);
207
+ const ciphertext = Buffer.concat([
208
+ cipher.update(Buffer.from(canonicalJson(input.payload))),
209
+ cipher.final(),
210
+ ]);
211
+ return {
212
+ schema: WRAPPED_KEY_ENVELOPE_SCHEMA,
213
+ alg: 'x25519-hkdf-sha256-aes-256-gcm',
214
+ ephemeralPublicKeyJwk: ephemeral.publicKey.export({ format: 'jwk' }),
215
+ iv: iv.toString('base64url'),
216
+ ciphertext: ciphertext.toString('base64url'),
217
+ tag: cipher.getAuthTag().toString('base64url'),
218
+ aadDigest: fingerprintPayload(input.aad),
219
+ createdAt: input.createdAt ?? new Date().toISOString(),
220
+ };
221
+ }
222
+ export function unwrapJsonFromX25519Envelope(input) {
223
+ if (input.envelope.schema !== WRAPPED_KEY_ENVELOPE_SCHEMA) {
224
+ throw new Error('Unsupported wrapped key envelope schema.');
225
+ }
226
+ if (input.envelope.alg !== 'x25519-hkdf-sha256-aes-256-gcm') {
227
+ throw new Error('Unsupported wrapped key envelope algorithm.');
228
+ }
229
+ const expectedAadDigest = fingerprintPayload(input.aad);
230
+ if (input.envelope.aadDigest !== expectedAadDigest) {
231
+ throw new Error('Wrapped key envelope AAD mismatch.');
232
+ }
233
+ const recipientPrivateKey = crypto.createPrivateKey({
234
+ key: input.recipientPrivateKeyJwk,
235
+ format: 'jwk',
236
+ });
237
+ const ephemeralPublicKey = crypto.createPublicKey({
238
+ key: input.envelope.ephemeralPublicKeyJwk,
239
+ format: 'jwk',
240
+ });
241
+ const sharedSecret = crypto.diffieHellman({
242
+ privateKey: recipientPrivateKey,
243
+ publicKey: ephemeralPublicKey,
244
+ });
245
+ const decipher = crypto.createDecipheriv('aes-256-gcm', deriveWrapKey(sharedSecret), Buffer.from(input.envelope.iv, 'base64url'));
246
+ decipher.setAAD(Buffer.from(canonicalJson(input.aad)));
247
+ decipher.setAuthTag(Buffer.from(input.envelope.tag, 'base64url'));
248
+ const plaintext = Buffer.concat([
249
+ decipher.update(Buffer.from(input.envelope.ciphertext, 'base64url')),
250
+ decipher.final(),
251
+ ]);
252
+ return JSON.parse(plaintext.toString('utf8'));
253
+ }
254
+ export function assertNoPrivateKeyMaterial(value, path = '$') {
255
+ if (Array.isArray(value)) {
256
+ value.forEach((item, index) => assertNoPrivateKeyMaterial(item, `${path}[${index}]`));
257
+ return;
258
+ }
259
+ if (!value || typeof value !== 'object')
260
+ return;
261
+ for (const [key, child] of Object.entries(value)) {
262
+ if (PRIVATE_JWK_FIELDS.has(key)) {
263
+ throw new Error(`Private key material is not allowed at ${path}.${key}.`);
264
+ }
265
+ assertNoPrivateKeyMaterial(child, `${path}.${key}`);
266
+ }
267
+ }
268
+ function deriveWrapKey(sharedSecret) {
269
+ return Buffer.from(crypto.hkdfSync('sha256', sharedSecret, Buffer.from('viewport-wrapped-key-envelope-salt-v1'), Buffer.from('viewport-wrapped-key-envelope/v1'), 32));
270
+ }
271
+ function canonicalize(value) {
272
+ if (Array.isArray(value))
273
+ return value.map((item) => canonicalize(item));
274
+ if (!value || typeof value !== 'object')
275
+ return value;
276
+ return Object.keys(value)
277
+ .sort()
278
+ .reduce((acc, key) => {
279
+ const child = value[key];
280
+ if (child !== undefined)
281
+ acc[key] = canonicalize(child);
282
+ return acc;
283
+ }, {});
284
+ }
285
+ //# sourceMappingURL=epoch-protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"epoch-protocol.js","sourceRoot":"","sources":["../../src/security/epoch-protocol.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import { type JsonValue } from './epoch-protocol.js';
2
+ import { type LocalPublicEpochPin } from './epoch-store.js';
3
+ export interface PublicEpochForPinning {
4
+ platformEpochId: string;
5
+ workspaceId: string;
6
+ subjectType: 'user' | 'team';
7
+ subjectId: string;
8
+ epoch: number;
9
+ schema: 'viewport.user_crypto_epoch/v1' | 'viewport.team_crypto_epoch/v1';
10
+ fingerprint: string;
11
+ encryptionPublicKeyJwk: JsonValue;
12
+ signingPublicKeyJwk: JsonValue;
13
+ previousEpochFingerprint?: string | null;
14
+ continuityPayload?: JsonValue | null;
15
+ continuitySignature?: string | null;
16
+ signedByEpochFingerprint?: string | null;
17
+ }
18
+ export declare function validateAndPinPublicEpoch(epoch: PublicEpochForPinning, home?: string): Promise<LocalPublicEpochPin>;
19
+ //# sourceMappingURL=epoch-public-pins.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"epoch-public-pins.d.ts","sourceRoot":"","sources":["../../src/security/epoch-public-pins.ts"],"names":[],"mappings":"AACA,OAAO,EAKL,KAAK,SAAS,EAEf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,kBAAkB,CAAC;AAE1B,MAAM,WAAW,qBAAqB;IACpC,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,+BAA+B,GAAG,+BAA+B,CAAC;IAC1E,WAAW,EAAE,MAAM,CAAC;IACpB,sBAAsB,EAAE,SAAS,CAAC;IAClC,mBAAmB,EAAE,SAAS,CAAC;IAC/B,wBAAwB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,iBAAiB,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IACrC,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,wBAAwB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1C;AAED,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,qBAAqB,EAC5B,IAAI,SAAc,GACjB,OAAO,CAAC,mBAAmB,CAAC,CAoD9B"}
@@ -0,0 +1,129 @@
1
+ import { configDir } from '../core/config.js';
2
+ import { epochFingerprint, verifyEpochTransition, } from './epoch-protocol.js';
3
+ import { getLocalPublicEpochPin, upsertLocalPublicEpochPin, } from './epoch-store.js';
4
+ export async function validateAndPinPublicEpoch(epoch, home = configDir()) {
5
+ const descriptor = publicEpochDescriptor(epoch);
6
+ const computedFingerprint = epochFingerprint(descriptor);
7
+ if (computedFingerprint !== epoch.fingerprint) {
8
+ throw new Error(`Fetched ${epoch.subjectType} epoch fingerprint mismatch for ${epoch.subjectId}.`);
9
+ }
10
+ const previous = await getLocalPublicEpochPin({
11
+ workspaceId: epoch.workspaceId,
12
+ subjectType: epoch.subjectType,
13
+ subjectId: epoch.subjectId,
14
+ }, home);
15
+ if (previous) {
16
+ if (epoch.epoch < previous.epoch) {
17
+ throw new Error(`Fetched ${epoch.subjectType} epoch rollback for ${epoch.subjectId}: ${epoch.epoch} < ${previous.epoch}.`);
18
+ }
19
+ if (epoch.epoch === previous.epoch && epoch.fingerprint !== previous.fingerprint) {
20
+ throw new Error(`Fetched ${epoch.subjectType} epoch replacement for ${epoch.subjectId} requires signed continuity.`);
21
+ }
22
+ if (epoch.epoch > previous.epoch) {
23
+ assertSignedContinuity({ previous, next: epoch });
24
+ }
25
+ }
26
+ return upsertLocalPublicEpochPin({
27
+ workspaceId: epoch.workspaceId,
28
+ subjectType: epoch.subjectType,
29
+ subjectId: epoch.subjectId,
30
+ platformEpochId: epoch.platformEpochId,
31
+ epoch: epoch.epoch,
32
+ schema: epoch.schema,
33
+ fingerprint: epoch.fingerprint,
34
+ encryptionPublicKeyJwk: epoch.encryptionPublicKeyJwk,
35
+ signingPublicKeyJwk: epoch.signingPublicKeyJwk,
36
+ previousEpochFingerprint: epoch.previousEpochFingerprint ?? null,
37
+ continuityPayload: epoch.continuityPayload ?? null,
38
+ continuitySignature: epoch.continuitySignature ?? null,
39
+ signedByEpochFingerprint: epoch.signedByEpochFingerprint ?? null,
40
+ }, home);
41
+ }
42
+ function assertSignedContinuity(input) {
43
+ if (input.next.previousEpochFingerprint !== input.previous.fingerprint) {
44
+ throw new Error(`Fetched ${input.next.subjectType} epoch ${input.next.epoch} does not continue from pinned epoch ${input.previous.epoch}.`);
45
+ }
46
+ if (!input.next.continuityPayload || !input.next.continuitySignature) {
47
+ throw new Error(`Fetched ${input.next.subjectType} epoch ${input.next.epoch} is missing signed continuity.`);
48
+ }
49
+ const signed = {
50
+ payload: epochTransitionPayload(input.next.continuityPayload),
51
+ signature: input.next.continuitySignature,
52
+ signedByEpochFingerprint: input.next.signedByEpochFingerprint ?? input.next.previousEpochFingerprint ?? '',
53
+ };
54
+ const ok = verifyEpochTransition({
55
+ signed,
56
+ signingPublicKeyJwk: input.previous.signingPublicKeyJwk,
57
+ expectedFromEpochFingerprint: input.previous.fingerprint,
58
+ expectedToEpochFingerprint: input.next.fingerprint,
59
+ });
60
+ if (!ok) {
61
+ throw new Error(`Fetched ${input.next.subjectType} epoch ${input.next.epoch} continuity signature is invalid.`);
62
+ }
63
+ }
64
+ function publicEpochDescriptor(epoch) {
65
+ return {
66
+ schema: epoch.schema,
67
+ workspaceId: epoch.workspaceId,
68
+ subjectType: epoch.subjectType,
69
+ subjectId: epoch.subjectId,
70
+ epoch: epoch.epoch,
71
+ encryptionPublicKeyJwk: epoch.encryptionPublicKeyJwk,
72
+ signingPublicKeyJwk: epoch.signingPublicKeyJwk,
73
+ previousEpochFingerprint: epoch.previousEpochFingerprint ?? null,
74
+ createdAt: 'pinning-fingerprint-input',
75
+ };
76
+ }
77
+ function epochTransitionPayload(value) {
78
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
79
+ throw new Error('Epoch continuity payload must be an object.');
80
+ }
81
+ const data = value;
82
+ return {
83
+ schema: 'viewport.epoch_transition/v1',
84
+ workspaceId: stringField(data, 'workspaceId'),
85
+ subjectType: subjectTypeField(data, 'subjectType'),
86
+ subjectId: stringField(data, 'subjectId'),
87
+ fromEpoch: numberField(data, 'fromEpoch'),
88
+ fromEpochFingerprint: stringField(data, 'fromEpochFingerprint'),
89
+ toEpoch: numberField(data, 'toEpoch'),
90
+ toEpochFingerprint: stringField(data, 'toEpochFingerprint'),
91
+ reason: reasonField(data, 'reason'),
92
+ createdAt: stringField(data, 'createdAt'),
93
+ };
94
+ }
95
+ function stringField(value, field) {
96
+ const child = value[field];
97
+ if (typeof child !== 'string' || child.trim() === '') {
98
+ throw new Error(`Epoch continuity payload missing ${field}.`);
99
+ }
100
+ return child;
101
+ }
102
+ function numberField(value, field) {
103
+ const child = value[field];
104
+ if (typeof child !== 'number') {
105
+ throw new Error(`Epoch continuity payload missing numeric ${field}.`);
106
+ }
107
+ return child;
108
+ }
109
+ function subjectTypeField(value, field) {
110
+ const child = stringField(value, field);
111
+ if (child !== 'user' && child !== 'team') {
112
+ throw new Error(`Epoch continuity payload has unsupported ${field}.`);
113
+ }
114
+ return child;
115
+ }
116
+ function reasonField(value, field) {
117
+ const child = stringField(value, field);
118
+ if (child === 'initial' ||
119
+ child === 'device_enrolled' ||
120
+ child === 'device_revoked' ||
121
+ child === 'member_added' ||
122
+ child === 'member_revoked' ||
123
+ child === 'manual_rotation' ||
124
+ child === 'recovery') {
125
+ return child;
126
+ }
127
+ throw new Error(`Epoch continuity payload has unsupported ${field}.`);
128
+ }
129
+ //# sourceMappingURL=epoch-public-pins.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"epoch-public-pins.js","sourceRoot":"","sources":["../../src/security/epoch-public-pins.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EACL,gBAAgB,EAChB,qBAAqB,GAKtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,sBAAsB,EACtB,yBAAyB,GAE1B,MAAM,kBAAkB,CAAC;AAkB1B,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,KAA4B,EAC5B,IAAI,GAAG,SAAS,EAAE;IAElB,MAAM,UAAU,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;IAChD,MAAM,mBAAmB,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;IACzD,IAAI,mBAAmB,KAAK,KAAK,CAAC,WAAW,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CACb,WAAW,KAAK,CAAC,WAAW,mCAAmC,KAAK,CAAC,SAAS,GAAG,CAClF,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,sBAAsB,CAC3C;QACE,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,SAAS,EAAE,KAAK,CAAC,SAAS;KAC3B,EACD,IAAI,CACL,CAAC;IAEF,IAAI,QAAQ,EAAE,CAAC;QACb,IAAI,KAAK,CAAC,KAAK,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CACb,WAAW,KAAK,CAAC,WAAW,uBAAuB,KAAK,CAAC,SAAS,KAAK,KAAK,CAAC,KAAK,MAAM,QAAQ,CAAC,KAAK,GAAG,CAC1G,CAAC;QACJ,CAAC;QACD,IAAI,KAAK,CAAC,KAAK,KAAK,QAAQ,CAAC,KAAK,IAAI,KAAK,CAAC,WAAW,KAAK,QAAQ,CAAC,WAAW,EAAE,CAAC;YACjF,MAAM,IAAI,KAAK,CACb,WAAW,KAAK,CAAC,WAAW,0BAA0B,KAAK,CAAC,SAAS,8BAA8B,CACpG,CAAC;QACJ,CAAC;QACD,IAAI,KAAK,CAAC,KAAK,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC;YACjC,sBAAsB,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IAED,OAAO,yBAAyB,CAC9B;QACE,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,eAAe,EAAE,KAAK,CAAC,eAAe;QACtC,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,sBAAsB,EAAE,KAAK,CAAC,sBAAsB;QACpD,mBAAmB,EAAE,KAAK,CAAC,mBAAmB;QAC9C,wBAAwB,EAAE,KAAK,CAAC,wBAAwB,IAAI,IAAI;QAChE,iBAAiB,EAAE,KAAK,CAAC,iBAAiB,IAAI,IAAI;QAClD,mBAAmB,EAAE,KAAK,CAAC,mBAAmB,IAAI,IAAI;QACtD,wBAAwB,EAAE,KAAK,CAAC,wBAAwB,IAAI,IAAI;KACjE,EACD,IAAI,CACL,CAAC;AACJ,CAAC;AAED,SAAS,sBAAsB,CAAC,KAG/B;IACC,IAAI,KAAK,CAAC,IAAI,CAAC,wBAAwB,KAAK,KAAK,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;QACvE,MAAM,IAAI,KAAK,CACb,WAAW,KAAK,CAAC,IAAI,CAAC,WAAW,UAAU,KAAK,CAAC,IAAI,CAAC,KAAK,wCAAwC,KAAK,CAAC,QAAQ,CAAC,KAAK,GAAG,CAC3H,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,iBAAiB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,mBAAmB,EAAE,CAAC;QACrE,MAAM,IAAI,KAAK,CACb,WAAW,KAAK,CAAC,IAAI,CAAC,WAAW,UAAU,KAAK,CAAC,IAAI,CAAC,KAAK,gCAAgC,CAC5F,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAA0B;QACpC,OAAO,EAAE,sBAAsB,CAAC,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC;QAC7D,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,mBAAmB;QACzC,wBAAwB,EACtB,KAAK,CAAC,IAAI,CAAC,wBAAwB,IAAI,KAAK,CAAC,IAAI,CAAC,wBAAwB,IAAI,EAAE;KACnF,CAAC;IACF,MAAM,EAAE,GAAG,qBAAqB,CAAC;QAC/B,MAAM;QACN,mBAAmB,EAAE,KAAK,CAAC,QAAQ,CAAC,mBAAmB;QACvD,4BAA4B,EAAE,KAAK,CAAC,QAAQ,CAAC,WAAW;QACxD,0BAA0B,EAAE,KAAK,CAAC,IAAI,CAAC,WAAW;KACnD,CAAC,CAAC;IACH,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,MAAM,IAAI,KAAK,CACb,WAAW,KAAK,CAAC,IAAI,CAAC,WAAW,UAAU,KAAK,CAAC,IAAI,CAAC,KAAK,mCAAmC,CAC/F,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,qBAAqB,CAAC,KAA4B;IACzD,OAAO;QACL,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,sBAAsB,EAAE,KAAK,CAAC,sBAAsB;QACpD,mBAAmB,EAAE,KAAK,CAAC,mBAAmB;QAC9C,wBAAwB,EAAE,KAAK,CAAC,wBAAwB,IAAI,IAAI;QAChE,SAAS,EAAE,2BAA2B;KACvC,CAAC;AACJ,CAAC;AAED,SAAS,sBAAsB,CAAC,KAAgB;IAC9C,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAChE,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;IACjE,CAAC;IACD,MAAM,IAAI,GAAG,KAAkC,CAAC;IAChD,OAAO;QACL,MAAM,EAAE,8BAA8B;QACtC,WAAW,EAAE,WAAW,CAAC,IAAI,EAAE,aAAa,CAAC;QAC7C,WAAW,EAAE,gBAAgB,CAAC,IAAI,EAAE,aAAa,CAAC;QAClD,SAAS,EAAE,WAAW,CAAC,IAAI,EAAE,WAAW,CAAC;QACzC,SAAS,EAAE,WAAW,CAAC,IAAI,EAAE,WAAW,CAAC;QACzC,oBAAoB,EAAE,WAAW,CAAC,IAAI,EAAE,sBAAsB,CAAC;QAC/D,OAAO,EAAE,WAAW,CAAC,IAAI,EAAE,SAAS,CAAC;QACrC,kBAAkB,EAAE,WAAW,CAAC,IAAI,EAAE,oBAAoB,CAAC;QAC3D,MAAM,EAAE,WAAW,CAAC,IAAI,EAAE,QAAQ,CAAC;QACnC,SAAS,EAAE,WAAW,CAAC,IAAI,EAAE,WAAW,CAAC;KAC1C,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,KAAgC,EAAE,KAAa;IAClE,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;IAC3B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QACrD,MAAM,IAAI,KAAK,CAAC,oCAAoC,KAAK,GAAG,CAAC,CAAC;IAChE,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,WAAW,CAAC,KAAgC,EAAE,KAAa;IAClE,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;IAC3B,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,4CAA4C,KAAK,GAAG,CAAC,CAAC;IACxE,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAgC,EAAE,KAAa;IACvE,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACxC,IAAI,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;QACzC,MAAM,IAAI,KAAK,CAAC,4CAA4C,KAAK,GAAG,CAAC,CAAC;IACxE,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,WAAW,CAClB,KAAgC,EAChC,KAAa;IAEb,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACxC,IACE,KAAK,KAAK,SAAS;QACnB,KAAK,KAAK,iBAAiB;QAC3B,KAAK,KAAK,gBAAgB;QAC1B,KAAK,KAAK,cAAc;QACxB,KAAK,KAAK,gBAAgB;QAC1B,KAAK,KAAK,iBAAiB;QAC3B,KAAK,KAAK,UAAU,EACpB,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,4CAA4C,KAAK,GAAG,CAAC,CAAC;AACxE,CAAC"}
@@ -0,0 +1,56 @@
1
+ import { transportFetch } from '../cli/network.js';
2
+ import { type LocalUserCryptoEpoch } from './epoch-store.js';
3
+ import { type JsonValue } from './epoch-protocol.js';
4
+ import { type CryptoEpochSyncTarget } from './epoch-sync.js';
5
+ export declare const USER_EPOCH_RECOVERY_BACKUP_SCHEMA = "viewport.user_epoch_recovery_backup/v1";
6
+ declare const USER_EPOCH_RECOVERY_ENVELOPE_SCHEMA = "viewport.user_epoch_recovery_envelope/v1";
7
+ declare const RECOVERY_KDF = "scrypt-sha256/v1";
8
+ interface UserKeyBackupResponse {
9
+ id: string;
10
+ workspace_id: string;
11
+ user_id: number | string;
12
+ user_crypto_epoch_id: string;
13
+ schema: typeof USER_EPOCH_RECOVERY_BACKUP_SCHEMA;
14
+ status: string;
15
+ kdf: typeof RECOVERY_KDF;
16
+ kdf_params: RecoveryKdfParams;
17
+ encrypted_payload: RecoveryEnvelope;
18
+ created_at?: string | null;
19
+ }
20
+ interface RecoveryKdfParams {
21
+ salt: string;
22
+ keyLength: number;
23
+ N: number;
24
+ r: number;
25
+ p: number;
26
+ }
27
+ interface RecoveryEnvelope {
28
+ schema: typeof USER_EPOCH_RECOVERY_ENVELOPE_SCHEMA;
29
+ alg: 'aes-256-gcm';
30
+ aad: JsonValue;
31
+ iv: string;
32
+ ciphertext: string;
33
+ tag: string;
34
+ aadDigest: string;
35
+ createdAt: string;
36
+ }
37
+ export declare function generateUserEpochRecoveryKey(): string;
38
+ export declare function createUserEpochRecoveryBackup(options: {
39
+ target: CryptoEpochSyncTarget;
40
+ recoveryKey: string;
41
+ home?: string;
42
+ fetchImpl?: typeof transportFetch;
43
+ }): Promise<UserKeyBackupResponse>;
44
+ export declare function restoreUserEpochFromRecoveryBackup(options: {
45
+ target: CryptoEpochSyncTarget;
46
+ recoveryKey: string;
47
+ home?: string;
48
+ fetchImpl?: typeof transportFetch;
49
+ }): Promise<{
50
+ backup: UserKeyBackupResponse;
51
+ restoredEpoch: LocalUserCryptoEpoch;
52
+ rotatedEpoch: LocalUserCryptoEpoch;
53
+ rotatedBackup: UserKeyBackupResponse;
54
+ }>;
55
+ export {};
56
+ //# sourceMappingURL=epoch-recovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"epoch-recovery.d.ts","sourceRoot":"","sources":["../../src/security/epoch-recovery.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD,OAAO,EAGL,KAAK,oBAAoB,EAC1B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAyB,KAAK,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAEpF,eAAO,MAAM,iCAAiC,2CAA2C,CAAC;AAE1F,QAAA,MAAM,mCAAmC,6CAA6C,CAAC;AACvF,QAAA,MAAM,YAAY,qBAAqB,CAAC;AAWxC,UAAU,qBAAqB;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,MAAM,EAAE,OAAO,iCAAiC,CAAC;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,OAAO,YAAY,CAAC;IACzB,UAAU,EAAE,iBAAiB,CAAC;IAC9B,iBAAiB,EAAE,gBAAgB,CAAC;IACpC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,UAAU,iBAAiB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,UAAU,gBAAgB;IACxB,MAAM,EAAE,OAAO,mCAAmC,CAAC;IACnD,GAAG,EAAE,aAAa,CAAC;IACnB,GAAG,EAAE,SAAS,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,4BAA4B,IAAI,MAAM,CAErD;AAED,wBAAsB,6BAA6B,CAAC,OAAO,EAAE;IAC3D,MAAM,EAAE,qBAAqB,CAAC;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,cAAc,CAAC;CACnC,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAkDjC;AAED,wBAAsB,kCAAkC,CAAC,OAAO,EAAE;IAChE,MAAM,EAAE,qBAAqB,CAAC;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,cAAc,CAAC;CACnC,GAAG,OAAO,CAAC;IACV,MAAM,EAAE,qBAAqB,CAAC;IAC9B,aAAa,EAAE,oBAAoB,CAAC;IACpC,YAAY,EAAE,oBAAoB,CAAC;IACnC,aAAa,EAAE,qBAAqB,CAAC;CACtC,CAAC,CAqCD"}