@claudian-collab/protocol 3.1.0 → 3.2.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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @claudian-collab/protocol
2
2
 
3
- The canonical shared Collab wire contract, produced from the
3
+ The canonical shared Collab wire and offline backup contract, produced from the
4
4
  [claudian-collab-protocol](https://github.com/YishenTu/claudian-collab-protocol) repository. Both Claudian
5
5
  (LAN client and Host) and Claudian Cloud Server consume this package; neither
6
6
  may maintain copied types, operation registries, codec maps, shared constants,
@@ -19,7 +19,7 @@ or compatibility rules.
19
19
  `collabMemberRef`)
20
20
  - Shared limits that client and server must agree on (`COLLAB_LIMITS`)
21
21
  - Protocol-version negotiation (`COLLAB_PROTOCOL_VERSION`, envelope decoding)
22
- - Canonical Project checkpoint profiles, logical records, authority-generation transfer, exact membership claims, target-signed redemption receipts, and Project retirement contracts
22
+ - Canonical Project checkpoint profiles, logical records, authority-generation transfer, exact membership claims, target-signed redemption receipts, offline backup operational continuity, and Project retirement contracts
23
23
  - Cloud binding v2 route construction/matching, bounded checkpoint streams, capability negotiation, strict success/error envelopes, private-development bootstrap, Project snapshot, and redacted event contracts
24
24
  - Markdown-derived Ticket-reference and Member-mention semantics shared by
25
25
  client rendering and authority derivation
@@ -37,7 +37,7 @@ fixed part of the detail so the whole detail stays within
37
37
  has one compatible final-serialization limit. Request comments and Ticket
38
38
  accepted relations also have shared authority-enforced total limits; summary
39
39
  counts let complete consumers reject partial or cross-snapshot assembly.
40
- Cloud binding v2 adds the authority-neutral Project snapshot, nine redacted durable event kinds plus `snapshot.required`, eleven capability tokens, the exact ordinary Project/Git route catalog, bounded authority-transfer artifact routes, and six private-development bootstrap bindings. The shared checkpoint container is exactly `checkpoint.json`, `coordination.ndjson`, and `repository.bundle`; portable profiles exclude engine storage, paths, credentials, tokens, private keys, and operational refs, while the backup profile may carry only protected claim-envelope metadata and ciphertext. Domain-separated canonical UTF-8 inputs define protected-claim AEAD associated data and bind every declared field of transferred-membership redemption receipts and authority-relinquishment proofs before consumer-owned Ed25519 signing or verification. Existing LAN v9 Join, invitation, endpoint, membership lifecycle, Host-transfer, snapshot, event, and HTTP bindings remain independently application-owned; the dedicated LAN authority-transfer transport binds these shared payloads without creating another shared operation registry.
40
+ Cloud binding v2 adds the authority-neutral Project snapshot, nine redacted durable event kinds plus `snapshot.required`, eleven capability tokens, the exact ordinary Project/Git route catalog, bounded authority-transfer artifact routes, and six private-development bootstrap bindings. The shared checkpoint container is exactly `checkpoint.json`, `coordination.ndjson`, and `repository.bundle`; authority-transfer and export retain wire-visible coordination format v1, while offline backup format v2 adds lifecycle journals, recovery evidence, claim hashes, public receipt verifiers, exact custody/redemption receipts, terminal replay facts, and protected claim-envelope metadata plus ciphertext. Portable profiles exclude engine storage, paths, credentials, tokens, private keys, and operational refs, and backups exclude raw claims and private keys. Domain-separated canonical UTF-8 inputs define protected-claim AEAD associated data and bind every declared field of transferred-membership redemption receipts and authority-relinquishment proofs before consumer-owned Ed25519 signing or verification. Existing LAN v9 Join, invitation, endpoint, membership lifecycle, Host-transfer, snapshot, event, and HTTP bindings remain independently application-owned; the dedicated LAN authority-transfer transport binds these shared payloads without creating another shared operation registry.
41
41
 
42
42
  ## Usage
43
43
 
@@ -62,7 +62,7 @@ part of the public surface.
62
62
 
63
63
  Package SemVer, canonical wire version, and Cloud binding version are independent concepts.
64
64
 
65
- - **Package version** (this `package.json`): `3.1.0`. Patch releases preserve
65
+ - **Package version** (this `package.json`): `3.2.0`. Patch releases preserve
66
66
  every existing public declaration and runtime behavior baseline. Minor
67
67
  releases may add backward-compatible API. Removing or changing an existing
68
68
  declaration, export, runtime behavior, codec, error, limit, ref rule,
@@ -70,7 +70,9 @@ Package SemVer, canonical wire version, and Cloud binding version are independen
70
70
  proven additive control operation may use a package minor release without a
71
71
  wire-version increase; existing operation declarations and fixtures must stay
72
72
  exact. Package 3 and wire 6 support exact transfer-claim batches and a
73
- source-pinned target receipt verifier. The package version never signals wire
73
+ source-pinned target receipt verifier. Package 3.2 adds offline backup
74
+ coordination format v2 without changing authority-transfer/export format v1,
75
+ canonical wire v6, or Cloud binding v2. The package version never signals wire
74
76
  compatibility by itself.
75
77
  - **Wire version** (`COLLAB_PROTOCOL_VERSION`): currently `6`. The supported
76
78
  range is exactly `[6, 6]`. This is independent from Cloud binding version `2` and the existing application
@@ -0,0 +1,164 @@
1
+ import { type CollabAuthorityRelinquishmentProof, type CollabAuthorityTransferReceiptVerifier, type CollabTransferredMembershipClaimCustodyReceipt, type CollabTransferredMembershipRedemptionReceipt } from './CollabAuthorityTransfer';
2
+ import { type CollabControlOperation } from './CollabControlOperationCodecs';
3
+ import { type CollabCheckpointAuthority, type CollabCheckpointBackupRecord, type CollabCheckpointGitRef, type CollabProjectCheckpointManifest } from './CollabProjectCheckpoint';
4
+ import type { CollabIsoTimestamp, CollabMemberId, CollabProjectId } from './types';
5
+ export declare const COLLAB_PROJECT_BACKUP_COORDINATION_FORMAT_VERSION: 2;
6
+ export declare const COLLAB_PROJECT_BACKUP_RECORD_KINDS: readonly ("member" | "request" | "ticket" | "project" | "request-comment" | "ticket-comment" | "ticket-relation" | "ticket-mention" | "cloud-event" | "cloud-event-cursor" | "idempotency-result" | "principal-binding" | "repository-placement" | "lifecycle-state" | "terminal-responder" | "protected-claim-envelope" | "tombstone" | "schema-catalog" | "server-compatibility" | "authority-volume-pair" | "lifecycle-journal" | "authority-transfer-recovery" | "transferred-membership-claim" | "transfer-receipt-key" | "transfer-claim-batch-receipt" | "transfer-redemption-receipt" | "terminal-principal" | "terminal-responder-replay" | "leave-former-principal-replay")[];
7
+ export type CollabProjectBackupRecordKind = typeof COLLAB_PROJECT_BACKUP_RECORD_KINDS[number];
8
+ interface BackupRecordBase<Kind extends string, Value> {
9
+ readonly kind: Kind;
10
+ readonly recordId: string;
11
+ readonly revision: number;
12
+ readonly value: Value;
13
+ }
14
+ export type CollabProjectBackupLifecycleKind = 'authority-transfer' | 'backup' | 'delete' | 'export' | 'leave' | 'retire';
15
+ export type CollabProjectBackupLifecycleState = 'active' | 'cancelled' | 'completed' | 'recovery-required';
16
+ export interface CollabProjectBackupInactiveRepositoryPublication {
17
+ readonly artifactKey: string;
18
+ readonly bundleByteCount: number;
19
+ readonly bundleSha256: string;
20
+ readonly objectFormat: 'sha1' | 'sha256';
21
+ readonly operationId: string;
22
+ readonly placementGeneration: number;
23
+ readonly projectId: CollabProjectId;
24
+ readonly publicationMarkerSha256: string;
25
+ readonly refs: readonly CollabCheckpointGitRef[];
26
+ readonly repositoryStorageKey: string;
27
+ readonly status: 'inactive';
28
+ readonly storageNodeId: string;
29
+ readonly validationMarkerSha256: string;
30
+ }
31
+ export interface CollabProjectBackupLanToCloudSourceEvidence {
32
+ readonly checkpointManifestSha256: string;
33
+ readonly principalId: string;
34
+ readonly proof: string;
35
+ readonly receiptKeyId: string;
36
+ readonly receiptPublicKey: string;
37
+ readonly schemaVersion: 1;
38
+ }
39
+ export interface CollabProjectBackupCloudToLanTargetEvidence {
40
+ readonly acceptanceIntentId: string;
41
+ readonly principalId: string;
42
+ readonly proof: string;
43
+ readonly receiptKeyId: string;
44
+ readonly receiptPublicKey: string;
45
+ readonly schemaVersion: 1;
46
+ }
47
+ export type CollabProjectBackupLifecycleJournalRecord = BackupRecordBase<'lifecycle-journal', {
48
+ readonly actorMemberId: CollabMemberId | null;
49
+ readonly batchRevision: number | null;
50
+ readonly batchSha256: string | null;
51
+ readonly checkpointSha256: string | null;
52
+ readonly createdAt: CollabIsoTimestamp;
53
+ readonly direction: 'cloud-to-lan' | 'lan-to-cloud' | null;
54
+ readonly expectedAuthorityGeneration: number;
55
+ readonly expectedPersonalRefOid: string | null;
56
+ readonly idempotencyKey: string;
57
+ readonly operationId: string;
58
+ readonly operationKind: CollabProjectBackupLifecycleKind;
59
+ readonly phase: string;
60
+ readonly projectId: CollabProjectId;
61
+ readonly recoveryFromPhase: string | null;
62
+ readonly requestFingerprint: string;
63
+ readonly resultSha256: string | null;
64
+ readonly scheduledAt: CollabIsoTimestamp;
65
+ readonly state: CollabProjectBackupLifecycleState;
66
+ readonly updatedAt: CollabIsoTimestamp;
67
+ }>;
68
+ export type CollabProjectBackupAuthorityTransferRecoveryRecord = BackupRecordBase<'authority-transfer-recovery', {
69
+ readonly cancellationRequestSha256: string | null;
70
+ readonly createdAt: CollabIsoTimestamp;
71
+ readonly expiresAt: CollabIsoTimestamp;
72
+ readonly inactivePublication: CollabProjectBackupInactiveRepositoryPublication | null;
73
+ readonly projectId: CollabProjectId;
74
+ readonly relinquishmentProof: CollabAuthorityRelinquishmentProof | null;
75
+ readonly sourceAuthority: CollabCheckpointAuthority;
76
+ readonly sourceHostMemberId: CollabMemberId | null;
77
+ readonly sourceEvidence: CollabProjectBackupLanToCloudSourceEvidence | null;
78
+ readonly sourceReopenSha256: string | null;
79
+ readonly stageSha256: string | null;
80
+ readonly targetActivationProof: string | null;
81
+ readonly targetActivationRequestSha256: string | null;
82
+ readonly targetAuthority: CollabCheckpointAuthority;
83
+ readonly targetHostMemberId: CollabMemberId | null;
84
+ readonly targetEvidence: CollabProjectBackupCloudToLanTargetEvidence | null;
85
+ readonly targetUrl: string;
86
+ readonly transferId: string;
87
+ readonly updatedAt: CollabIsoTimestamp;
88
+ }>;
89
+ export type CollabProjectBackupTransferredMembershipClaimRecord = BackupRecordBase<'transferred-membership-claim', {
90
+ readonly batchRevision: number;
91
+ readonly checkpointSha256: string;
92
+ readonly claimSha256: string;
93
+ readonly createdAt: CollabIsoTimestamp;
94
+ readonly expiresAt: CollabIsoTimestamp;
95
+ readonly memberId: CollabMemberId;
96
+ readonly operationIntentId: string | null;
97
+ readonly projectId: CollabProjectId;
98
+ readonly redemptionReceiptId: string | null;
99
+ readonly state: 'redeemed' | 'revoked' | 'unclaimed';
100
+ readonly targetPrincipalId: string | null;
101
+ readonly transferId: string;
102
+ readonly updatedAt: CollabIsoTimestamp;
103
+ }>;
104
+ export type CollabProjectBackupTransferReceiptKeyRecord = BackupRecordBase<'transfer-receipt-key', CollabAuthorityTransferReceiptVerifier & {
105
+ readonly createdAt: CollabIsoTimestamp;
106
+ }>;
107
+ export type CollabProjectBackupTransferClaimBatchReceiptRecord = BackupRecordBase<'transfer-claim-batch-receipt', {
108
+ readonly receipt: CollabTransferredMembershipClaimCustodyReceipt;
109
+ }>;
110
+ export type CollabProjectBackupTransferRedemptionReceiptRecord = BackupRecordBase<'transfer-redemption-receipt', {
111
+ readonly acknowledgedAt: CollabIsoTimestamp | null;
112
+ readonly projectId: CollabProjectId;
113
+ readonly receipt: CollabTransferredMembershipRedemptionReceipt;
114
+ }>;
115
+ export type CollabProjectBackupTerminalPrincipalRecord = BackupRecordBase<'terminal-principal', {
116
+ readonly acknowledgedAt: CollabIsoTimestamp | null;
117
+ readonly memberId: CollabMemberId;
118
+ readonly operationId: string;
119
+ readonly operationKind: 'authority-transfer' | 'retire';
120
+ readonly principalId: string;
121
+ readonly projectId: CollabProjectId;
122
+ }>;
123
+ export type CollabProjectBackupTerminalResponderReplayRecord = BackupRecordBase<'terminal-responder-replay', {
124
+ readonly memberId: CollabMemberId;
125
+ readonly operationId: string;
126
+ readonly projectId: CollabProjectId;
127
+ readonly requestSha256: string;
128
+ }>;
129
+ export type CollabProjectBackupLeaveFormerPrincipalReplayRecord = BackupRecordBase<'leave-former-principal-replay', {
130
+ readonly completedAt: CollabIsoTimestamp | null;
131
+ readonly createdAt: CollabIsoTimestamp;
132
+ readonly expectedPersonalRefOid: string;
133
+ readonly expiresAt: CollabIsoTimestamp;
134
+ readonly intentId: string;
135
+ readonly memberId: CollabMemberId;
136
+ readonly operationId: string;
137
+ readonly principalSha256: string;
138
+ readonly projectId: CollabProjectId;
139
+ readonly requestFingerprint: string;
140
+ readonly resultSha256: string | null;
141
+ readonly state: 'completed' | 'recovering';
142
+ }>;
143
+ export type CollabProjectBackupContinuityRecord = CollabProjectBackupLifecycleJournalRecord | CollabProjectBackupAuthorityTransferRecoveryRecord | CollabProjectBackupTransferredMembershipClaimRecord | CollabProjectBackupTransferReceiptKeyRecord | CollabProjectBackupTransferClaimBatchReceiptRecord | CollabProjectBackupTransferRedemptionReceiptRecord | CollabProjectBackupTerminalPrincipalRecord | CollabProjectBackupTerminalResponderReplayRecord | CollabProjectBackupLeaveFormerPrincipalReplayRecord;
144
+ type CollabProjectBackupBaseRecord = Exclude<CollabCheckpointBackupRecord, {
145
+ readonly kind: 'lifecycle-state';
146
+ }>;
147
+ export type CollabProjectBackupRecord = CollabProjectBackupBaseRecord | CollabProjectBackupContinuityRecord;
148
+ export type CollabProjectBackupCheckpointManifest = Omit<CollabProjectCheckpointManifest, 'coordinationFormatVersion' | 'profile'> & {
149
+ readonly coordinationFormatVersion: typeof COLLAB_PROJECT_BACKUP_COORDINATION_FORMAT_VERSION;
150
+ readonly profile: 'backup';
151
+ };
152
+ export declare function collabProjectBackupIdempotencyRecordId(input: Readonly<{
153
+ readonly idempotencyKey: string;
154
+ readonly memberId: CollabMemberId;
155
+ readonly operation: CollabControlOperation;
156
+ readonly projectId: CollabProjectId;
157
+ }>): string;
158
+ export declare function decodeCollabProjectBackupCheckpointManifest(value: unknown): CollabProjectBackupCheckpointManifest;
159
+ export declare function encodeCollabProjectBackupCheckpointManifestCanonicalJson(manifest: CollabProjectBackupCheckpointManifest): string;
160
+ export declare function encodeCollabProjectBackupCheckpointManifestDigestInput(manifest: CollabProjectBackupCheckpointManifest): string;
161
+ export declare function decodeCollabProjectBackupCheckpointCoordinationNdjson(value: string): readonly CollabProjectBackupRecord[];
162
+ export declare function encodeCollabProjectBackupCheckpointCoordinationNdjson(records: readonly CollabProjectBackupRecord[]): string;
163
+ export declare function validateCollabProjectBackupCheckpointConsistency(manifest: CollabProjectBackupCheckpointManifest, records: readonly CollabProjectBackupRecord[]): readonly CollabProjectBackupRecord[];
164
+ export {};