@cairnkeep/cli 2.26.0 → 2.27.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/CHANGELOG.md +23 -0
- package/docs/README.md +4 -0
- package/docs/learning/CURRICULUM-MAP.md +1 -1
- package/docs/learning/FEATURE-GUIDE.md +7 -1
- package/docs/learning/lessons/L00-why-cairnkeep.md +1 -1
- package/docs/learning/lessons/L01-safe-trial.md +3 -3
- package/docs/learning/lessons/L02-installation.md +2 -2
- package/docs/learning/lessons/L03-first-project.md +1 -1
- package/docs/learning/lessons/L19-validated-skill-improvement.md +1 -1
- package/docs/learning/lessons/L20-mcp-tool-profiles.md +1 -1
- package/docs/learning/lessons/L21-context-packs.md +1 -1
- package/docs/learning/lessons/L22-native-windows.md +2 -2
- package/docs/learning/lessons/L23-guided-setup.md +1 -1
- package/docs/learning/lessons/L24-okf-exchange.md +1 -1
- package/docs/learning/lessons/L25-playbooks.md +1 -1
- package/docs/learning/lessons/L26-context-intelligence.md +1 -1
- package/docs/learning/lessons/L27-ecosystem-evidence.md +1 -1
- package/docs/learning/lessons/L28-security-assurance.md +1 -1
- package/docs/learning/lessons/L29-team-continuity.md +10 -1
- package/docs/learning/tracks/operator.md +3 -0
- package/docs/learning/video-scripts/V29-team-continuity.md +12 -2
- package/docs/operating.md +4 -0
- package/docs/privacy-and-data-flow.md +9 -0
- package/docs/releasing.md +6 -0
- package/docs/storage.md +9 -0
- package/docs/team-onboarding.md +4 -0
- package/docs/team-operations.md +127 -0
- package/docs/team.md +10 -4
- package/examples/eval/bundled-fake.json +1 -1
- package/mcp-memory-server/dist/team-audit.js +41 -0
- package/mcp-memory-server/dist/team-cli.js +68 -27
- package/mcp-memory-server/dist/team-errors.js +7 -0
- package/mcp-memory-server/dist/team-files.js +28 -0
- package/mcp-memory-server/dist/team-mcp.js +4 -3
- package/mcp-memory-server/dist/team-pages.js +40 -0
- package/mcp-memory-server/dist/team-store.js +98 -39
- package/package.json +1 -1
- package/scripts/cairn-cli.mjs +1 -1
- package/scripts/completion.sh +8 -3
- package/scripts/test-ci-sharding.sh +6 -1
- package/scripts/test-completion.sh +5 -2
- package/scripts/test-release-cache.mjs +16 -0
- package/scripts/test-security-baseline.sh +3 -0
- package/scripts/test-smoke-timings.mjs +19 -0
- package/scripts/test-team-docs.sh +16 -1
- package/scripts/test-team-installed.mjs +11 -0
- package/scripts/test-team-lab-env.mjs +9 -0
- package/scripts/test-team-operations.mjs +31 -0
- package/scripts/test-team-operations.sh +5 -0
- package/scripts/verify-published-release.mjs +11 -2
- package/scripts/windows-platform.mjs +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,29 @@ All notable user-facing changes are documented here. This project follows
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
## [2.27.0] - 2026-10-26
|
|
9
|
+
|
|
10
|
+
### Team operations
|
|
11
|
+
|
|
12
|
+
- Add opt-in bounded paging to team listings with authenticated,
|
|
13
|
+
credential/project/filter/policy/view-bound cursors and unchanged legacy arrays.
|
|
14
|
+
- Add payload-free capacity diagnostics, metadata-only audit export/verification
|
|
15
|
+
and backup-bound, exact-digest archival. Default to a no-write plan; explicit
|
|
16
|
+
apply atomically retains a chain checkpoint and frees the active audit prefix.
|
|
17
|
+
Retain external archives/backups; do not enable automatic retention or sharing.
|
|
18
|
+
- Keep existing team stores/snapshots at v1 until explicit archival; compacted
|
|
19
|
+
stores use v2 and require the new server/admin binary. Restore revokes copied
|
|
20
|
+
credentials. Document offline operation and old-format rollback requirements.
|
|
21
|
+
- Add disposable cross-process continuity endurance and adversarial/installed
|
|
22
|
+
package controls. Update operating/privacy/storage and learning/video briefs;
|
|
23
|
+
no new recording, independent-human trial or production admission is claimed.
|
|
24
|
+
|
|
25
|
+
### Release maintenance
|
|
26
|
+
|
|
27
|
+
- Use fresh process-scoped npm verification metadata/cache without weakening
|
|
28
|
+
signature, provenance or exact-byte checks. Record per-contract smoke timings
|
|
29
|
+
and rebalance complete Windows shards using measured hosted durations.
|
|
30
|
+
|
|
8
31
|
## [2.26.0] - 2026-10-26
|
|
9
32
|
|
|
10
33
|
### Guided team onboarding
|
package/docs/README.md
CHANGED
|
@@ -76,6 +76,10 @@ linked guides rather than the project landing page.
|
|
|
76
76
|
|
|
77
77
|
## Overlays and teams
|
|
78
78
|
|
|
79
|
+
- [Team operations](team-operations.md): scoped paging, capacity, explicit
|
|
80
|
+
backup-bound audit archival and synthetic endurance from 2.27.0. Availability
|
|
81
|
+
is not permission to enable sharing.
|
|
82
|
+
|
|
79
83
|
- [Team continuity preview](team.md) documents the default-off, separately
|
|
80
84
|
authenticated shared-memory store, human review, local MCP bridge and recovery.
|
|
81
85
|
It ships as an opt-in experimental preview from 2.25.0, not general production admission. The
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Cairnkeep feature guide
|
|
2
2
|
|
|
3
|
-
**Baseline:** Cairnkeep 2.
|
|
3
|
+
**Baseline:** Cairnkeep 2.27.0
|
|
4
4
|
|
|
5
5
|
This is the step-back map for choosing and operating Cairnkeep features. The
|
|
6
6
|
[course labs](https://github.com/cairnkeep/cairnkeep-course-labs) provide one
|
|
@@ -197,6 +197,12 @@ supports drift-aware recovery. Both client and team API must be 2.26 or newer.
|
|
|
197
197
|
These commands do not enroll users or enable sharing automatically. See the
|
|
198
198
|
[guided recipe](../team-onboarding.md#guided-connection-226-or-newer).
|
|
199
199
|
|
|
200
|
+
From 2.27.0, [team operations](../team-operations.md) adds optional authenticated
|
|
201
|
+
paging, capacity diagnostics and offline, backup-bound audit archival. Upgrade
|
|
202
|
+
client/API/admin binaries together. Archival defaults to a no-write plan and
|
|
203
|
+
requires exact-digest apply; it alone upgrades the separate team store to v2.
|
|
204
|
+
Keep every archive and backup. Installation never compacts or activates a team.
|
|
205
|
+
|
|
200
206
|
Authority is rechecked per request. Backup/restore validates integrity and
|
|
201
207
|
revokes restored credentials; retention is manual, and logical deletion is not
|
|
202
208
|
physical erasure. Feature/profile changes require restarting the bridge;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
**Status:** Ready
|
|
4
4
|
**Track:** Quickstart
|
|
5
5
|
**Time:** 15 minutes
|
|
6
|
-
**Tested with:** Cairnkeep 2.
|
|
6
|
+
**Tested with:** Cairnkeep 2.27.0
|
|
7
7
|
|
|
8
8
|
## Outcome
|
|
9
9
|
|
|
@@ -26,7 +26,7 @@ ephemeral; the named course volume is persistent.
|
|
|
26
26
|
1. Pull the public image:
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
|
-
podman pull ghcr.io/cairnkeep/cairnkeep:2.
|
|
29
|
+
podman pull ghcr.io/cairnkeep/cairnkeep:2.27.0
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
2. Start the stdio server with a read-only root filesystem and no Linux
|
|
@@ -38,7 +38,7 @@ ephemeral; the named course volume is persistent.
|
|
|
38
38
|
--read-only --cap-drop=all --security-opt=no-new-privileges \
|
|
39
39
|
--tmpfs=/tmp:rw,noexec,nosuid,size=64m,mode=1777 \
|
|
40
40
|
--volume cairnkeep-course-data:/data:Z,U \
|
|
41
|
-
ghcr.io/cairnkeep/cairnkeep:2.
|
|
41
|
+
ghcr.io/cairnkeep/cairnkeep:2.27.0 stdio
|
|
42
42
|
```
|
|
43
43
|
|
|
44
44
|
3. The process waits quietly for MCP input. Press `Ctrl-C` after confirming it
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
**Status:** Ready
|
|
4
4
|
**Track:** Quickstart
|
|
5
5
|
**Time:** 25 minutes
|
|
6
|
-
**Tested with:** Cairnkeep 2.
|
|
6
|
+
**Tested with:** Cairnkeep 2.27.0 and Node.js 22 or newer
|
|
7
7
|
|
|
8
8
|
## Outcome
|
|
9
9
|
|
|
@@ -47,7 +47,7 @@ sync. Codex project trust remains an explicit operator decision.
|
|
|
47
47
|
2. Install Cairnkeep:
|
|
48
48
|
|
|
49
49
|
```bash
|
|
50
|
-
npm install --global @cairnkeep/cli@2.
|
|
50
|
+
npm install --global @cairnkeep/cli@2.27.0
|
|
51
51
|
cairn --version
|
|
52
52
|
```
|
|
53
53
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
**Status:** Ready
|
|
4
4
|
**Track:** Operator
|
|
5
5
|
**Time:** 30 minutes
|
|
6
|
-
**Tested with:** Cairnkeep 2.
|
|
6
|
+
**Tested with:** Cairnkeep 2.27.0, Windows x64, and Node.js 22 or newer
|
|
7
7
|
|
|
8
8
|
## Outcome
|
|
9
9
|
|
|
@@ -16,7 +16,7 @@ perform a reversible uninstall without relying on WSL or Git Bash.
|
|
|
16
16
|
From PowerShell:
|
|
17
17
|
|
|
18
18
|
```powershell
|
|
19
|
-
npm install --global @cairnkeep/cli@2.
|
|
19
|
+
npm install --global @cairnkeep/cli@2.27.0
|
|
20
20
|
cairn version
|
|
21
21
|
|
|
22
22
|
$Lab = Join-Path $env:TEMP 'Cairnkeep Windows Lab'
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
**Status:** Brief; opt-in experimental preview in Cairnkeep 2.25.0
|
|
4
4
|
**Compatibility:** Cairnkeep 2.25.0 or newer for manual connection; 2.26.0 or newer
|
|
5
|
-
on both client and team API for guided connection
|
|
5
|
+
on both client and team API for guided connection; 2.27.0 or newer client/API/admin
|
|
6
|
+
for operations. Node 22.13 or newer for team storage.
|
|
6
7
|
Use a matching source checkout for the executable regression exercises below.
|
|
7
8
|
Installing the released CLI does not enable team sharing.
|
|
8
9
|
|
|
@@ -51,6 +52,14 @@ real users or introduce real data during this exercise.
|
|
|
51
52
|
|
|
52
53
|
## Guided client exercise (2.26 or newer)
|
|
53
54
|
|
|
55
|
+
The separate [operations exercise](../../team-operations.md) requires
|
|
56
|
+
2.27.0 or newer client/API/admin binaries. Practice paging, capacity,
|
|
57
|
+
read-only backup, metadata export, no-write archive plan, exact apply and fresh
|
|
58
|
+
v2 restore only in a disposable lab. Keep archive files/private backups, explain
|
|
59
|
+
old-server rollback requirements, and distinguish active suffix integrity from
|
|
60
|
+
complete retained history. The longer two-process endurance run is synthetic
|
|
61
|
+
transport/policy evidence, not independent human review or native UI validation.
|
|
62
|
+
|
|
54
63
|
Use the [guided connection recipe](../../team-onboarding.md#guided-connection-next-release--matching-source-checkout)
|
|
55
64
|
with a disposable project and the operator's synthetic workload-reader file.
|
|
56
65
|
Run `cairn team connect` once without `--apply`: inspect its selected project,
|
|
@@ -23,6 +23,9 @@
|
|
|
23
23
|
Do not enable it in production before the independent review and approved pilot.
|
|
24
24
|
Version 2.26.0 adds guided additive connection, client
|
|
25
25
|
diagnostics and disconnect/recovery exercises; no production enrollment.
|
|
26
|
+
Version 2.27.0 adds optional paging, capacity and explicit offline audit
|
|
27
|
+
archival. Rehearse only in a disposable lab; retain backups and stop older
|
|
28
|
+
writers before the explicit v2 store-format change.
|
|
26
29
|
|
|
27
30
|
All modules are optional. The track is complete when the operator can add and
|
|
28
31
|
remove each integration without breaking the standalone local workflow and can
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# V29 - Remember together without sharing everything
|
|
2
2
|
|
|
3
|
-
Status: technical rehearsal brief for Cairnkeep 2.
|
|
4
|
-
opt-in preview introduced in 2.25.0. Not a recorded or
|
|
3
|
+
Status: technical rehearsal brief for Cairnkeep 2.27.0 operations and guided
|
|
4
|
+
onboarding to the opt-in preview introduced in 2.25.0. Not a recorded or
|
|
5
|
+
independently rehearsed lesson.
|
|
5
6
|
Target: 10–12 minutes, experienced-developer audience. Describe a released
|
|
6
7
|
experimental preview, not a generally production-admitted team service.
|
|
7
8
|
Use the [isolated pilot guide](../../team-pilot.md) for a separately authorized
|
|
@@ -77,6 +78,15 @@ remote MCP. Call out OIDC, team packs and multi-organization tenancy as deferred
|
|
|
77
78
|
|
|
78
79
|
## Recording contract
|
|
79
80
|
|
|
81
|
+
For an operations supplement on 2.27.0 or newer client/API/admin binaries, use the
|
|
82
|
+
[operations recipe](../../team-operations.md). Show the capacity counters,
|
|
83
|
+
optional page envelope and stale-cursor refusal, then a stopped disposable
|
|
84
|
+
service, read-only backup, audit export, no-write archive plan and exact apply.
|
|
85
|
+
Pause on “older server binaries cannot reopen v2”; keep all backups and tokens
|
|
86
|
+
off screen. Show the synthetic endurance counts without claiming real human
|
|
87
|
+
consent, native-harness UI coverage or a quality benchmark. Do not record these
|
|
88
|
+
commands against an older CLI/API; this remains a rehearsal brief.
|
|
89
|
+
|
|
80
90
|
Use legible real terminals, short scene changes, natural pauses and emphasis
|
|
81
91
|
around each changed authority boundary. Keep credentials, personal memory,
|
|
82
92
|
source excerpts from private projects and raw snapshot text off screen.
|
package/docs/operating.md
CHANGED
|
@@ -1556,6 +1556,10 @@ The 2.26.0 guided client workflow is documented in
|
|
|
1556
1556
|
authenticated project/credential metadata, and `team disconnect` preserves
|
|
1557
1557
|
personal memory and credentials. Both client and team API must support 2.26's
|
|
1558
1558
|
connection check. No ordinary setup or production sharing is enabled implicitly.
|
|
1559
|
+
From 2.27.0, [team operations](team-operations.md) covers optional paging,
|
|
1560
|
+
capacity and offline, backup-bound audit archival. Keep matching client/API/admin
|
|
1561
|
+
binaries, stop older writers and retain all archives/backups. The no-write plan
|
|
1562
|
+
does not change a store; only explicit exact-digest apply upgrades it to v2.
|
|
1559
1563
|
The internal governed review and approved isolated native pilot are complete;
|
|
1560
1564
|
independent production review and a deployment-specific approved real-data pilot
|
|
1561
1565
|
are still required before using real organization data.
|
|
@@ -712,6 +712,15 @@ they do not authenticate a publisher or make extracted statements true.
|
|
|
712
712
|
|
|
713
713
|
## Team preview flow and isolation
|
|
714
714
|
|
|
715
|
+
The 2.27.0 [operations workflow](team-operations.md) adds only explicit
|
|
716
|
+
local audit export/archival, not automatic collection, sharing or deletion.
|
|
717
|
+
Audit exports contain activity/subject metadata and digests, not selected memory
|
|
718
|
+
values or bearer tokens; keep them private. Full backups still contain selected
|
|
719
|
+
team values and credential hashes. Doctor verifies active history from a stored
|
|
720
|
+
checkpoint, not unseen external archive retention. Digests are integrity checks,
|
|
721
|
+
not publisher authentication or secure erasure. Optional cursors are bound to
|
|
722
|
+
credentials and the visible query view; every page still checks current access.
|
|
723
|
+
|
|
715
724
|
The default-off [team preview](team.md) reads no personal memory automatically.
|
|
716
725
|
Only explicitly supplied, inspected text becomes an immutable project proposal;
|
|
717
726
|
only review by a different human credential publishes a shared revision.
|
package/docs/releasing.md
CHANGED
|
@@ -100,6 +100,12 @@ npm supporting registry-signature and provenance verification. Use `--gh PATH`
|
|
|
100
100
|
or `--npm PATH` for explicit tool selection; stale trust data or unsupported
|
|
101
101
|
flags fail closed rather than skipping a check. No runtime dependency is added.
|
|
102
102
|
|
|
103
|
+
The npm verification install and signature audit use a fresh cache inside the
|
|
104
|
+
disposable verification prefix and explicitly request online metadata. Ambient
|
|
105
|
+
offline/prefer-offline settings cannot hide a newly published version behind
|
|
106
|
+
an older cached package listing. This writes no global npm configuration and
|
|
107
|
+
does not relax exact bytes, registry authority, signatures or provenance checks.
|
|
108
|
+
|
|
103
109
|
The tool checks successful maintained CI, security and publication workflows, immutable
|
|
104
110
|
tag/commit/tree binding, retained CI candidate checksums and exact release-asset
|
|
105
111
|
bytes, CycloneDX 1.6, registry bytes/integrity, npm signatures/attestations, both
|
package/docs/storage.md
CHANGED
|
@@ -605,6 +605,15 @@ no separate prompt or retrieved-content log.
|
|
|
605
605
|
|
|
606
606
|
## Separate team store (opt-in 2.25 preview)
|
|
607
607
|
|
|
608
|
+
From 2.27.0, [team operations](team-operations.md) keep unarchived stores/snapshots
|
|
609
|
+
at v1. Only explicit offline archive/apply changes this team database to v2,
|
|
610
|
+
retaining the terminal sequence/hash and archive/backup digests. All exported
|
|
611
|
+
segments/backups remain external private files. New snapshots include the
|
|
612
|
+
checkpoint; restore revokes credentials and invalidates paging cursors. The
|
|
613
|
+
cursor signing key is local metadata, not exported as a credential. Ordinary
|
|
614
|
+
memory, trajectories, context packs and their layouts are unchanged. Old server
|
|
615
|
+
binaries cannot reopen the v2 store; retain a pre-archive v1 backup for rollback.
|
|
616
|
+
|
|
608
617
|
[Team continuity](team.md) keeps organization/project records in a separate
|
|
609
618
|
`team.db` under `CAIRN_TEAM_BASE_DIR` (default `~/.cairnkeep/team`). Built-in
|
|
610
619
|
SQLite transactions serialize state and audit across processes; personal
|
package/docs/team-onboarding.md
CHANGED
|
@@ -206,6 +206,10 @@ subscription use is authorized by this guide.
|
|
|
206
206
|
|
|
207
207
|
## Deployment readiness
|
|
208
208
|
|
|
209
|
+
The [operations guide](team-operations.md) adds paging, capacity diagnostics
|
|
210
|
+
and backup-bound explicit audit archival from 2.27.0. Use matching upgraded
|
|
211
|
+
client/API/admin binaries. Do not infer enrollment or admission from it.
|
|
212
|
+
|
|
209
213
|
Before requesting a real-data pilot, record an owner and evidence for:
|
|
210
214
|
|
|
211
215
|
- **Purpose:** project IDs, participants, data classes, one continuity use case,
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# Team operations: bounded history without automatic deletion
|
|
2
|
+
|
|
3
|
+
Available from **Cairnkeep 2.27.0**. Use 2.27.0 or newer client/API/admin
|
|
4
|
+
binaries for paging and archival; older releases do not include these commands.
|
|
5
|
+
The team preview remains default off and is not general production admission.
|
|
6
|
+
|
|
7
|
+
## Optional pagination
|
|
8
|
+
|
|
9
|
+
`list`, `history`, `proposals`, `audit` and `search` accept an optional `page`:
|
|
10
|
+
|
|
11
|
+
```json
|
|
12
|
+
{"organization":"demo-org","project":"alpha","operation":"list","page":{"size":20}}
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
The result is `{ "items": [...], "next_cursor": "..." }`; the final cursor
|
|
16
|
+
is `null`. Without `page`, existing bounded arrays and ordering remain unchanged.
|
|
17
|
+
Sizes are 1–100, or 1–10 for search. The existing team MCP list/search/history
|
|
18
|
+
tools accept the same optional object. No admin/review tool is added to MCP.
|
|
19
|
+
CLI equivalents are `--page-size N --cursor CURSOR`. Repeat the same project,
|
|
20
|
+
operation, filters and page size when continuing.
|
|
21
|
+
|
|
22
|
+
Cursors are authenticated and bound to the credential, project, roles/policy,
|
|
23
|
+
filters and visible result set. Tampering or cross-identity reuse fails;
|
|
24
|
+
changed results cause a conflict requiring a new first page. Every call checks
|
|
25
|
+
current membership, expiry and revocation. Cursor validity is not authorization.
|
|
26
|
+
Audit paging freezes an upper sequence so its own read events do not invalidate
|
|
27
|
+
the traversal. New events are visible in a fresh traversal. Restore invalidates
|
|
28
|
+
old cursors; its new credentials require a fresh traversal too.
|
|
29
|
+
|
|
30
|
+
## Capacity before refusal
|
|
31
|
+
|
|
32
|
+
`cairn team doctor --data DIR` remains local, metadata-only and non-mutating.
|
|
33
|
+
It reports record/audit entries, UTF-8 bytes, ceilings, remaining space and
|
|
34
|
+
`available`, `near-limit` (80%) or `exhausted` status. These are diagnostics,
|
|
35
|
+
not a guarantee that the next write fits. Records remain bounded at 32,768 and
|
|
36
|
+
16 MiB. Ordinary audit admission is 99,000 events/16 MiB, with a separate local
|
|
37
|
+
operator reserve of 1,000 events/256 KiB. Nothing is evicted automatically.
|
|
38
|
+
Archiving audit does not free record capacity.
|
|
39
|
+
|
|
40
|
+
## Offline, exact-digest archival
|
|
41
|
+
|
|
42
|
+
Only the trusted local OS operator can archive. **Stop the team API and bridge
|
|
43
|
+
writers first**, and use the matching new admin binary. Existing older server
|
|
44
|
+
processes cannot be retroactively made schema-aware. Do not archive a store
|
|
45
|
+
while an older service still has it open.
|
|
46
|
+
|
|
47
|
+
Choose private paths outside source trees; ancestors must not be writable by
|
|
48
|
+
other users/groups. Keep the backup and archive on durable protected storage.
|
|
49
|
+
The following paths are placeholders, not production defaults:
|
|
50
|
+
|
|
51
|
+
```sh
|
|
52
|
+
CAIRN_TEAM=1 cairn team doctor --data /absolute/private/team
|
|
53
|
+
CAIRN_TEAM=1 cairn team backup --data /absolute/private/team --read-only \
|
|
54
|
+
--output /absolute/private/backups/pre-archive.json
|
|
55
|
+
CAIRN_TEAM=1 cairn team audit-export --data /absolute/private/team \
|
|
56
|
+
--backup /absolute/private/backups/pre-archive.json \
|
|
57
|
+
--output /absolute/private/backups/audit-segment.json
|
|
58
|
+
CAIRN_TEAM=1 cairn team audit-verify \
|
|
59
|
+
--input /absolute/private/backups/audit-segment.json
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`--read-only` makes a consistent backup without adding an audit event, including
|
|
63
|
+
when the local reserve is full. Normal backup retains its existing audit event.
|
|
64
|
+
The export verifies its backup against current state, writes exclusively with
|
|
65
|
+
private permissions and file fsync (plus a directory flush on POSIX), and changes
|
|
66
|
+
no database state. Node cannot flush directory handles on Windows; protect and
|
|
67
|
+
retain the exported files on reliable storage before applying compaction.
|
|
68
|
+
It contains audit
|
|
69
|
+
metadata, not memory values or raw bearer tokens. Names and activity are still
|
|
70
|
+
sensitive; an export is not a public report.
|
|
71
|
+
|
|
72
|
+
Use the returned **archive_digest**, not a memory or backup digest:
|
|
73
|
+
|
|
74
|
+
```sh
|
|
75
|
+
# No-write plan:
|
|
76
|
+
CAIRN_TEAM=1 cairn team audit-archive --data /absolute/private/team \
|
|
77
|
+
--input /absolute/private/backups/audit-segment.json \
|
|
78
|
+
--backup /absolute/private/backups/pre-archive.json --confirm ARCHIVE_DIGEST
|
|
79
|
+
# Repeat the exact command with --apply to compact the verified active prefix.
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Wrong/tampered/stale backups, archives or confirmation fail. Any intervening
|
|
83
|
+
audited operation makes the plan stale: stop writers and produce a fresh pair.
|
|
84
|
+
Apply atomically records the archive/backup digests and terminal sequence/hash,
|
|
85
|
+
removes the active audit prefix, and appends an archival event. A failed database
|
|
86
|
+
transaction rolls back checkpoint, schema change and removal together. No file
|
|
87
|
+
is removed or overwritten. Keep **all segments and backups** under an explicit
|
|
88
|
+
operator-owned retention policy; no background job or default expiry is added.
|
|
89
|
+
|
|
90
|
+
## Compatibility, recovery and limits of evidence
|
|
91
|
+
|
|
92
|
+
Unarchived stores and snapshots stay version 1. Explicit archival changes only
|
|
93
|
+
this separate team store to version 2; subsequent snapshots carry its checkpoint.
|
|
94
|
+
Older server/admin binaries reject reopening that store. Legacy remote clients
|
|
95
|
+
can still use unchanged non-paged API calls with the new service. To roll back
|
|
96
|
+
the server format, use the retained pre-archive v1 backup in a fresh location;
|
|
97
|
+
never point an older binary at the compacted database. Restore continues to
|
|
98
|
+
revoke every copied credential. Reissue credentials and approve reactivation
|
|
99
|
+
explicitly; never overwrite a live store with a restore.
|
|
100
|
+
|
|
101
|
+
Doctor and snapshot validation check the active audit suffix anchored at its
|
|
102
|
+
checkpoint. They do **not** open external archives or prove full historical
|
|
103
|
+
retention. Verify retained segments with `audit-verify`; pass `--previous FILE`
|
|
104
|
+
to check the adjacent archive link. One successful segment check is not a claim
|
|
105
|
+
that every earlier segment is present. Digests provide integrity, not publisher
|
|
106
|
+
authenticity, independent timestamping or protection against a malicious OS owner.
|
|
107
|
+
Compaction is not secure erasure: backups, archives and SQLite pages may retain
|
|
108
|
+
data. Audit capacity still fails closed if operators take no action.
|
|
109
|
+
|
|
110
|
+
## Synthetic continuity endurance
|
|
111
|
+
|
|
112
|
+
From a matching built source checkout, in a private disposable lab:
|
|
113
|
+
|
|
114
|
+
```sh
|
|
115
|
+
lab=$(mktemp -d)
|
|
116
|
+
CAIRN_TEAM_SOAK=1 node mcp-memory-server/scripts/run-team-continuity-soak.mjs \
|
|
117
|
+
--cycles 120 --duration-ms 1200000 --out "$lab/report.json"
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
This exercises two actual stdio MCP client processes across working folders,
|
|
121
|
+
separate API process restarts (including an unclean termination), private
|
|
122
|
+
token-file rotation, revoked credentials, audit
|
|
123
|
+
archival and fresh restore. Its human-class reviewer is a **synthetic policy
|
|
124
|
+
fixture**, not actual human consent. No paid model, provider, real memory or
|
|
125
|
+
production configuration is used. Reports contain counts, digests and latency,
|
|
126
|
+
not selected text or bearer credentials. This is transport/authorization
|
|
127
|
+
continuity evidence, not a native-harness UI trial or a model-quality benchmark.
|
package/docs/team.md
CHANGED
|
@@ -214,13 +214,19 @@ store are refused before any uninstall changes; a store selected only through
|
|
|
214
214
|
|
|
215
215
|
## Bounded preview and admission
|
|
216
216
|
|
|
217
|
+
From 2.27.0, optional pagination, capacity diagnostics and explicitly confirmed
|
|
218
|
+
audit archival are available in [team operations](team-operations.md). Upgrade
|
|
219
|
+
the client, API and admin binary before using these operations.
|
|
220
|
+
|
|
217
221
|
Selected values are at most 64 KiB UTF-8; requests 512 KiB; responses 2 MiB;
|
|
218
222
|
snapshots 64 MiB. Records are capped at 32,768 and 16 MiB of stored JSON;
|
|
219
|
-
audit at
|
|
223
|
+
ordinary audit at 99,000 events and 16 MiB, with a separate
|
|
224
|
+
1,000-event/256 KiB OS-operator reserve.
|
|
220
225
|
Limits fail closed rather than discarding records. Back up and review retention
|
|
221
|
-
before approaching them;
|
|
222
|
-
Retrieval is bounded (100 list/history items, ten search results);
|
|
223
|
-
|
|
226
|
+
before approaching them; archival is offline, manual and backup-bound, never
|
|
227
|
+
automatic. Retrieval is bounded (100 list/history items, ten search results);
|
|
228
|
+
optional authenticated paging is available from 2.27.0. HTTP separately limits
|
|
229
|
+
malformed authentication
|
|
224
230
|
per connection address and authenticated requests per subject to 120 per minute;
|
|
225
231
|
invalid token-shaped credentials receive ten attempts per token digest. Each
|
|
226
232
|
budget holds at most 512 identities, and invalid authentication cannot consume
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"identifier":"cairn-offline-fake-v1","package_version":"2.
|
|
1
|
+
{"identifier":"cairn-offline-fake-v1","package_version":"2.27.0","schema_version":1,"task_set_digest":"13e95379f35839593047ec34521a65a8fa3ab92bd3993bca9dc8bf5c4a9ff36f"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { TeamError } from './team-errors.js';
|
|
4
|
+
const id = z.string().regex(/^[a-z0-9][a-z0-9-]{0,63}$/);
|
|
5
|
+
const digest = z.string().regex(/^[a-f0-9]{64}$/);
|
|
6
|
+
export const teamAuditCheckpointSchema = z.object({ sequence: z.number().int().positive(), digest, archive_digest: digest, backup_digest: digest, previous_archive_digest: digest.nullable() }).strict();
|
|
7
|
+
export const teamAuditRowSchema = z.object({ sequence: z.number().int().positive(), organization: id, project: id.or(z.literal('')), value: z.string().max(4096), digest }).strict();
|
|
8
|
+
export const teamAuditEntrySchema = z.object({ schema_version: z.literal(1), sequence: z.number().int().positive(), organization: id, project: id.or(z.literal('')), subject: id, credential_class: z.enum(['human', 'workload', 'local-os']), operation: z.enum(['project-create', 'member-set', 'credential-revoke', 'credential-issue', 'memory-delete', 'list', 'audit', 'read', 'history', 'search', 'propose', 'proposals', 'proposal-show', 'review', 'snapshot', 'restore', 'connection-check', 'audit-archive']), result: z.enum(['accepted', 'denied', 'conflict', 'invalid']), object_digest: digest.nullable(), previous_digest: digest.nullable(), request_id: z.string().uuid(), at: z.iso.datetime() }).strict();
|
|
9
|
+
const archiveSchema = z.object({ schema_version: z.literal(1), organization: id, backup_digest: digest, previous_checkpoint: teamAuditCheckpointSchema.nullable(), entries: z.array(teamAuditRowSchema).min(1).max(100000), digest }).strict();
|
|
10
|
+
const hash = (text) => createHash('sha256').update(text).digest('hex');
|
|
11
|
+
export function verifyTeamAuditRows(organization, rows, checkpoint) {
|
|
12
|
+
try {
|
|
13
|
+
let sequence = checkpoint?.sequence ?? 0, previous = checkpoint?.digest ?? null, bytes = 0;
|
|
14
|
+
for (const row of rows) {
|
|
15
|
+
const entry = teamAuditEntrySchema.parse(JSON.parse(row.value));
|
|
16
|
+
bytes += Buffer.byteLength(row.value);
|
|
17
|
+
if (row.organization !== organization || row.sequence !== ++sequence || entry.sequence !== sequence || entry.organization !== organization || entry.project !== row.project || entry.previous_digest !== previous || hash(row.value) !== row.digest)
|
|
18
|
+
throw new Error();
|
|
19
|
+
previous = row.digest;
|
|
20
|
+
}
|
|
21
|
+
if (bytes > 16 * 1024 * 1024 + 256 * 1024)
|
|
22
|
+
throw new Error();
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
throw new TeamError('integrity');
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export function verifyTeamAuditArchive(input) {
|
|
29
|
+
try {
|
|
30
|
+
if (Buffer.byteLength(JSON.stringify(input)) > 64 * 1024 * 1024)
|
|
31
|
+
throw new Error();
|
|
32
|
+
const archive = archiveSchema.parse(input), { digest, ...body } = archive;
|
|
33
|
+
if (hash(JSON.stringify(body)) !== digest)
|
|
34
|
+
throw new Error();
|
|
35
|
+
verifyTeamAuditRows(archive.organization, archive.entries, archive.previous_checkpoint);
|
|
36
|
+
return archive;
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
throw new TeamError('integrity');
|
|
40
|
+
}
|
|
41
|
+
}
|