@remnic/core 9.69.61 → 9.69.63
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/dist/access-admin-ops-surface.js +4 -4
- package/dist/access-authorization-probe.js +5 -5
- package/dist/access-boundary.js +4 -4
- package/dist/access-cli.js +20 -20
- package/dist/access-extraction-force-flush.js +4 -4
- package/dist/access-http-briefing.js +5 -5
- package/dist/access-http-query.js +4 -4
- package/dist/access-http.js +16 -16
- package/dist/access-identity-continuity-surface.js +4 -4
- package/dist/access-lcm-surface.js +4 -4
- package/dist/access-mcp.js +11 -11
- package/dist/access-namespace-preflight.js +4 -4
- package/dist/access-observe-write-surface.js +4 -4
- package/dist/access-operations-batch.js +5 -5
- package/dist/access-operations.js +10 -10
- package/dist/access-recall-concurrency.js +4 -4
- package/dist/access-recall-response.js +4 -4
- package/dist/access-recall-surface.js +4 -4
- package/dist/access-service.js +4 -4
- package/dist/access-surface-catalog.js +6 -6
- package/dist/{chunk-2C5Z7CWB.js → chunk-24TJ77TT.js} +2 -2
- package/dist/{chunk-LY3SDHMI.js → chunk-3MSMBVA3.js} +2 -2
- package/dist/{chunk-2L5DIVDU.js → chunk-4EEDRKRT.js} +2 -2
- package/dist/{chunk-WLZYGLJ4.js → chunk-5MA7ZLPD.js} +5 -7
- package/dist/chunk-5MA7ZLPD.js.map +1 -0
- package/dist/{chunk-XOLVM3AT.js → chunk-5WXJE5TV.js} +2 -2
- package/dist/{chunk-NLE6TSLG.js → chunk-BLVHDY2U.js} +5 -7
- package/dist/chunk-BLVHDY2U.js.map +1 -0
- package/dist/{chunk-4IFSMCRS.js → chunk-FEHVG4C4.js} +2 -2
- package/dist/{chunk-DC5CTLCZ.js → chunk-FTNV5476.js} +8 -8
- package/dist/{chunk-M4PHCEPU.js → chunk-LAEW4S43.js} +2 -2
- package/dist/{chunk-XN4CPSCN.js → chunk-LVGVXG22.js} +2 -2
- package/dist/{chunk-4P3ZBL5E.js → chunk-PZEXA6CM.js} +2 -2
- package/dist/{chunk-NORFVW2H.js → chunk-RA3C46VX.js} +2 -2
- package/dist/{chunk-YL2W6NUG.js → chunk-TPRBJF46.js} +3 -3
- package/dist/{chunk-TQAXUYUE.js → chunk-TQC6ELJO.js} +2 -2
- package/dist/{chunk-TM7S5UHD.js → chunk-U6HXB2OG.js} +2 -2
- package/dist/{chunk-WD32KTVI.js → chunk-VXGB766B.js} +3 -3
- package/dist/{chunk-ZNFHWNDM.js → chunk-W5UAB6EH.js} +3 -3
- package/dist/{chunk-ZJ6MEVTX.js → chunk-WAR75CRY.js} +8 -8
- package/dist/{chunk-KIOXEHWF.js → chunk-WKNWC46C.js} +2 -2
- package/dist/{chunk-K7S2IMGJ.js → chunk-ZDZJ2PG4.js} +309 -12
- package/dist/{chunk-K7S2IMGJ.js.map → chunk-ZDZJ2PG4.js.map} +1 -1
- package/dist/cli.js +17 -17
- package/dist/external-wiki-access.js +5 -5
- package/dist/extraction.js +3 -3
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -20
- package/dist/memory-browse-operations.js +5 -5
- package/dist/model-registry.d.ts.map +1 -1
- package/dist/model-registry.js +1 -1
- package/dist/orchestrator.js +20 -20
- package/dist/profiling.d.ts.map +1 -1
- package/dist/profiling.js +1 -1
- package/dist/recall-navigation-operations.js +5 -5
- package/dist/recall-navigation.js +4 -4
- package/dist/security/audit-memory-cli.d.ts.map +1 -1
- package/dist/security/audit-memory.d.ts +10 -0
- package/dist/security/audit-memory.d.ts.map +1 -1
- package/dist/security/injection-screen.d.ts +1 -2
- package/dist/security/injection-screen.d.ts.map +1 -1
- package/dist/summarizer.js +2 -2
- package/dist/support-passport/index.js +7 -7
- package/package.json +12 -2
- package/src/index.ts +1 -1
- package/src/model-registry.test.ts +22 -1
- package/src/model-registry.ts +7 -6
- package/src/profiling.test.ts +20 -1
- package/src/profiling.ts +7 -7
- package/src/security/audit-memory-cli.test.ts +90 -0
- package/src/security/audit-memory-cli.ts +7 -0
- package/src/security/audit-memory.ts +14 -0
- package/src/security/injection-screen.test.ts +245 -0
- package/src/security/injection-screen.ts +341 -11
- package/dist/chunk-NLE6TSLG.js.map +0 -1
- package/dist/chunk-WLZYGLJ4.js.map +0 -1
- /package/dist/{chunk-2C5Z7CWB.js.map → chunk-24TJ77TT.js.map} +0 -0
- /package/dist/{chunk-LY3SDHMI.js.map → chunk-3MSMBVA3.js.map} +0 -0
- /package/dist/{chunk-2L5DIVDU.js.map → chunk-4EEDRKRT.js.map} +0 -0
- /package/dist/{chunk-XOLVM3AT.js.map → chunk-5WXJE5TV.js.map} +0 -0
- /package/dist/{chunk-4IFSMCRS.js.map → chunk-FEHVG4C4.js.map} +0 -0
- /package/dist/{chunk-DC5CTLCZ.js.map → chunk-FTNV5476.js.map} +0 -0
- /package/dist/{chunk-M4PHCEPU.js.map → chunk-LAEW4S43.js.map} +0 -0
- /package/dist/{chunk-XN4CPSCN.js.map → chunk-LVGVXG22.js.map} +0 -0
- /package/dist/{chunk-4P3ZBL5E.js.map → chunk-PZEXA6CM.js.map} +0 -0
- /package/dist/{chunk-NORFVW2H.js.map → chunk-RA3C46VX.js.map} +0 -0
- /package/dist/{chunk-YL2W6NUG.js.map → chunk-TPRBJF46.js.map} +0 -0
- /package/dist/{chunk-TQAXUYUE.js.map → chunk-TQC6ELJO.js.map} +0 -0
- /package/dist/{chunk-TM7S5UHD.js.map → chunk-U6HXB2OG.js.map} +0 -0
- /package/dist/{chunk-WD32KTVI.js.map → chunk-VXGB766B.js.map} +0 -0
- /package/dist/{chunk-ZNFHWNDM.js.map → chunk-W5UAB6EH.js.map} +0 -0
- /package/dist/{chunk-ZJ6MEVTX.js.map → chunk-WAR75CRY.js.map} +0 -0
- /package/dist/{chunk-KIOXEHWF.js.map → chunk-WKNWC46C.js.map} +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { MemoryFile, MemoryFrontmatter } from "../types.js";
|
|
2
2
|
import type { InjectionScreenProfile } from "./injection-screen.js";
|
|
3
|
+
import { type SecurityConfigProjection } from "../capabilities.js";
|
|
3
4
|
export type AuditMemoryFindingCategory = "injection-signature" | "write-burst" | "authority-escalation";
|
|
4
5
|
export interface AuditMemoryFinding {
|
|
5
6
|
memoryId: string;
|
|
@@ -46,6 +47,15 @@ export interface AuditMemoryReport {
|
|
|
46
47
|
}>;
|
|
47
48
|
};
|
|
48
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* The screen profile an audit sweep must use, resolved through the shared
|
|
52
|
+
* security capability plan (#1523) rather than read off config (#3078). The
|
|
53
|
+
* sweep matches the live write path, so a memory this deployment would
|
|
54
|
+
* quarantine on write does not survive once stored; a deployment with the
|
|
55
|
+
* screen DISABLED keeps the `default` weighting, because the sweep must
|
|
56
|
+
* never be stricter than the configured write path.
|
|
57
|
+
*/
|
|
58
|
+
export declare function auditScreenProfile(config: SecurityConfigProjection): InjectionScreenProfile;
|
|
49
59
|
export declare function auditMemoryStore(options: AuditMemoryStoreOptions): Promise<AuditMemoryReport>;
|
|
50
60
|
export declare function formatAuditMemoryReport(report: AuditMemoryReport): string;
|
|
51
61
|
//# sourceMappingURL=audit-memory.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit-memory.d.ts","sourceRoot":"","sources":["../../src/security/audit-memory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEjE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"audit-memory.d.ts","sourceRoot":"","sources":["../../src/security/audit-memory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEjE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AACpE,OAAO,EAA+B,KAAK,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAIhG,MAAM,MAAM,0BAA0B,GAClC,qBAAqB,GACrB,aAAa,GACb,sBAAsB,CAAC;AAE3B,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,0BAA0B,CAAC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,eAAe,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IACzC,mBAAmB,CAAC,EAAE,MAAM,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IAClD,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IAC/D,iCAAiC,CAC/B,QAAQ,EAAE,UAAU,EACpB,KAAK,EAAE,OAAO,CAAC,iBAAiB,CAAC,EACjC,SAAS,CAAC,EAAE;QACV,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,EAAE,CAAC,EAAE,IAAI,CAAC;KACX,GACA,OAAO,CAAC,OAAO,CAAC,CAAC;CACrB;AAED,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,mFAAmF;IACnF,OAAO,CAAC,EAAE,sBAAsB,CAAC;IACjC,GAAG,CAAC,EAAE,IAAI,CAAC;IACX,OAAO,EAAE,kBAAkB,CAAC;CAC7B;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,kBAAkB,EAAE,CAAC;IAC/B,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE;QACf,UAAU,EAAE,MAAM,CAAC;QACnB,IAAI,EAAE,MAAM,CAAC;QACb,iBAAiB,EAAE,MAAM,CAAC;QAC1B,SAAS,EAAE,MAAM,CAAC;QAClB,eAAe,EAAE,KAAK,CAAC;YAAE,WAAW,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KAChE,CAAC;CACH;AAqJD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,wBAAwB,GAAG,sBAAsB,CAG3F;AAED,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAwFnG;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAuBzE"}
|
|
@@ -15,6 +15,5 @@ export interface InjectionScreenResult {
|
|
|
15
15
|
}
|
|
16
16
|
export type InjectionScreenProfile = "default" | "hardened";
|
|
17
17
|
export declare const INJECTION_SCREEN_THRESHOLD = 4;
|
|
18
|
-
|
|
19
|
-
export declare function screenCandidateFact(content: string, profile?: InjectionScreenProfile): InjectionScreenResult;
|
|
18
|
+
export declare function screenCandidateFact(rawContent: string, profile?: InjectionScreenProfile): InjectionScreenResult;
|
|
20
19
|
//# sourceMappingURL=injection-screen.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"injection-screen.d.ts","sourceRoot":"","sources":["../../src/security/injection-screen.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,sBAAsB,EAAE,CAAC;IACnC,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,MAAM,sBAAsB,GAAG,SAAS,GAAG,UAAU,CAAC;AAwC5D,eAAO,MAAM,0BAA0B,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"injection-screen.d.ts","sourceRoot":"","sources":["../../src/security/injection-screen.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,sBAAsB,EAAE,CAAC;IACnC,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,MAAM,sBAAsB,GAAG,SAAS,GAAG,UAAU,CAAC;AAwC5D,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAud5C,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,sBAAkC,GAC1C,qBAAqB,CA4BvB"}
|
package/dist/summarizer.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
HourlySummarizer,
|
|
3
3
|
summarizeHourlyStatus
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-5WXJE5TV.js";
|
|
5
5
|
import "./chunk-6DNMUYEE.js";
|
|
6
6
|
import "./chunk-S4DDLTPX.js";
|
|
7
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-5MA7ZLPD.js";
|
|
8
8
|
import "./chunk-62JTOLEX.js";
|
|
9
9
|
import "./chunk-QM2SPLKQ.js";
|
|
10
10
|
import "./chunk-JUXOTY6J.js";
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
SUPPORT_PASSPORT_MODEL_RESULT_PATH,
|
|
5
5
|
SupportPassportModelBridge,
|
|
6
6
|
parseSupportPassportModelJob
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-LAEW4S43.js";
|
|
8
8
|
import {
|
|
9
9
|
DEFAULT_SUPPORT_PASSPORT_CONFIG,
|
|
10
10
|
parseSupportPassportConfig
|
|
@@ -14,8 +14,8 @@ import {
|
|
|
14
14
|
buildSupportPassportPublicRequestHandler,
|
|
15
15
|
composeSupportPassportExternalRequestHandlers,
|
|
16
16
|
normalizeSupportPassportNetworkAddress
|
|
17
|
-
} from "../chunk-
|
|
18
|
-
import "../chunk-
|
|
17
|
+
} from "../chunk-LVGVXG22.js";
|
|
18
|
+
import "../chunk-24TJ77TT.js";
|
|
19
19
|
import {
|
|
20
20
|
SUPPORT_PASSPORT_DRAFT_MAX_CONTENT_CHARACTERS,
|
|
21
21
|
SUPPORT_PASSPORT_DRAFT_MAX_MEMORIES,
|
|
@@ -56,7 +56,7 @@ import {
|
|
|
56
56
|
notifySupportPassportCommitted,
|
|
57
57
|
resolveSupportPassportModelRoutePlan,
|
|
58
58
|
syncDirectoryForDurability
|
|
59
|
-
} from "../chunk-
|
|
59
|
+
} from "../chunk-VXGB766B.js";
|
|
60
60
|
import "../chunk-W4F3C7N7.js";
|
|
61
61
|
import "../chunk-MPC7TYTZ.js";
|
|
62
62
|
import "../chunk-ZHXSOMYH.js";
|
|
@@ -69,7 +69,7 @@ import "../chunk-PJSK6OJM.js";
|
|
|
69
69
|
import "../chunk-GNVZQ5JN.js";
|
|
70
70
|
import "../chunk-YN2UN7N3.js";
|
|
71
71
|
import "../chunk-ROBHL3GL.js";
|
|
72
|
-
import "../chunk-
|
|
72
|
+
import "../chunk-5WXJE5TV.js";
|
|
73
73
|
import "../chunk-6DNMUYEE.js";
|
|
74
74
|
import "../chunk-P5FPO2BR.js";
|
|
75
75
|
import "../chunk-6ET2VII7.js";
|
|
@@ -103,8 +103,8 @@ import "../chunk-EI6V5UXY.js";
|
|
|
103
103
|
import "../chunk-KKNZ7PUZ.js";
|
|
104
104
|
import "../chunk-AERXJCOG.js";
|
|
105
105
|
import "../chunk-754XN6LX.js";
|
|
106
|
-
import "../chunk-
|
|
107
|
-
import "../chunk-
|
|
106
|
+
import "../chunk-BLVHDY2U.js";
|
|
107
|
+
import "../chunk-5MA7ZLPD.js";
|
|
108
108
|
import "../chunk-62JTOLEX.js";
|
|
109
109
|
import "../chunk-QM2SPLKQ.js";
|
|
110
110
|
import "../chunk-JUXOTY6J.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remnic/core",
|
|
3
|
-
"version": "9.69.
|
|
3
|
+
"version": "9.69.63",
|
|
4
4
|
"description": "Framework-agnostic Remnic memory engine — orchestrator, storage, extraction, search, trust zones",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -2620,6 +2620,16 @@
|
|
|
2620
2620
|
"remnic-source": "./src/session-integrity.ts",
|
|
2621
2621
|
"import": "./dist/session-integrity.js"
|
|
2622
2622
|
},
|
|
2623
|
+
"./recall-handles": {
|
|
2624
|
+
"types": "./dist/recall-handles.d.ts",
|
|
2625
|
+
"remnic-source": "./src/recall-handles.ts",
|
|
2626
|
+
"import": "./dist/recall-handles.js"
|
|
2627
|
+
},
|
|
2628
|
+
"./recall-handles.js": {
|
|
2629
|
+
"types": "./dist/recall-handles.d.ts",
|
|
2630
|
+
"remnic-source": "./src/recall-handles.ts",
|
|
2631
|
+
"import": "./dist/recall-handles.js"
|
|
2632
|
+
},
|
|
2623
2633
|
"./session-namespace-bindings": {
|
|
2624
2634
|
"types": "./dist/session-namespace-bindings.d.ts",
|
|
2625
2635
|
"remnic-source": "./src/session-namespace-bindings.ts",
|
|
@@ -3307,7 +3317,7 @@
|
|
|
3307
3317
|
"core"
|
|
3308
3318
|
],
|
|
3309
3319
|
"peerDependencies": {
|
|
3310
|
-
"@remnic/coding-graph": "^9.69.
|
|
3320
|
+
"@remnic/coding-graph": "^9.69.63"
|
|
3311
3321
|
},
|
|
3312
3322
|
"peerDependenciesMeta": {
|
|
3313
3323
|
"@remnic/coding-graph": {
|
package/src/index.ts
CHANGED
|
@@ -389,7 +389,7 @@ export {
|
|
|
389
389
|
} from "./trust-zones.js";
|
|
390
390
|
export { DEFAULT_UNTRUSTED_ORIGINS, HARDENED_UNTRUSTED_ORIGINS, classifyOrigin, isUntrustedOrigin, parseOriginClass, renderAuthorityFence, type MemoryInjectionDefenseMode, type OriginClass } from "./security/origin-authority.js";
|
|
391
391
|
export { INJECTION_SCREEN_THRESHOLD, screenCandidateFact, type InjectionScreenFinding, type InjectionScreenProfile, type InjectionScreenResult } from "./security/injection-screen.js";
|
|
392
|
-
export { auditMemoryStore, formatAuditMemoryReport, type AuditMemoryReport } from "./security/audit-memory.js";
|
|
392
|
+
export { auditMemoryStore, auditScreenProfile, formatAuditMemoryReport, type AuditMemoryReport } from "./security/audit-memory.js";
|
|
393
393
|
// Access layer (HTTP + MCP + schema validation)
|
|
394
394
|
// ---------------------------------------------------------------------------
|
|
395
395
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
|
-
import { mkdtempSync, rmSync } from "node:fs";
|
|
2
|
+
import { existsSync, mkdtempSync, rmSync } from "node:fs";
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import test from "node:test";
|
|
@@ -36,3 +36,24 @@ test("calculateContextSizes ignores invalid or tiny override values before budge
|
|
|
36
36
|
rmSync(dir, { recursive: true, force: true });
|
|
37
37
|
}
|
|
38
38
|
});
|
|
39
|
+
|
|
40
|
+
test("construction never creates the registry dir; the first save does", () => {
|
|
41
|
+
const dir = mkdtempSync(join(tmpdir(), "remnic-model-registry-"));
|
|
42
|
+
const registryDir = join(dir, ".registry");
|
|
43
|
+
try {
|
|
44
|
+
const registry = new ModelRegistry(dir);
|
|
45
|
+
// Constructing a registry happens on every plugin registration, including
|
|
46
|
+
// read-only discovery passes, so it must not touch the memory dir.
|
|
47
|
+
assert.equal(existsSync(registryDir), false, "no dir before anything is cached");
|
|
48
|
+
registry.setCapabilities("local-model", {
|
|
49
|
+
maxPositionEmbeddings: 32_768,
|
|
50
|
+
contextWindow: 32_768,
|
|
51
|
+
supportsExtendedContext: false,
|
|
52
|
+
typicalOutputTokens: 2_048,
|
|
53
|
+
source: "manual",
|
|
54
|
+
});
|
|
55
|
+
assert.equal(existsSync(registryDir), true, "the first cached model creates it");
|
|
56
|
+
} finally {
|
|
57
|
+
rmSync(dir, { recursive: true, force: true });
|
|
58
|
+
}
|
|
59
|
+
});
|
package/src/model-registry.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import { log } from "./logger.js";
|
|
7
7
|
import fs from "node:fs";
|
|
8
|
-
import { join } from "node:path";
|
|
8
|
+
import { dirname, join } from "node:path";
|
|
9
9
|
|
|
10
10
|
export interface ModelCapabilities {
|
|
11
11
|
modelId: string;
|
|
@@ -116,11 +116,7 @@ export class ModelRegistry {
|
|
|
116
116
|
private readonly CACHE_TTL_DAYS = 7;
|
|
117
117
|
|
|
118
118
|
constructor(memoryDir: string) {
|
|
119
|
-
|
|
120
|
-
if (!fs.existsSync(registryDir)) {
|
|
121
|
-
fs.mkdirSync(registryDir, { recursive: true });
|
|
122
|
-
}
|
|
123
|
-
this.registryPath = join(registryDir, "model-capabilities.json");
|
|
119
|
+
this.registryPath = join(memoryDir, ".registry", "model-capabilities.json");
|
|
124
120
|
this.data = this.loadRegistry();
|
|
125
121
|
}
|
|
126
122
|
|
|
@@ -140,6 +136,11 @@ export class ModelRegistry {
|
|
|
140
136
|
|
|
141
137
|
private saveRegistry(): void {
|
|
142
138
|
try {
|
|
139
|
+
// Created on first save, never at construction: building a registry
|
|
140
|
+
// happens on every plugin registration, including read-only discovery
|
|
141
|
+
// passes, and must not touch the operator's memory dir.
|
|
142
|
+
const registryDir = dirname(this.registryPath);
|
|
143
|
+
if (!fs.existsSync(registryDir)) fs.mkdirSync(registryDir, { recursive: true });
|
|
143
144
|
fs.writeFileSync(this.registryPath, JSON.stringify(this.data, null, 2));
|
|
144
145
|
} catch (err) {
|
|
145
146
|
log.warn(`ModelRegistry: failed to save registry: ${err}`);
|
package/src/profiling.test.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
|
-
import { mkdtempSync, readdirSync, rmSync } from "node:fs";
|
|
2
|
+
import { existsSync, mkdtempSync, readdirSync, rmSync } from "node:fs";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { tmpdir } from "node:os";
|
|
5
5
|
import test, { describe } from "node:test";
|
|
@@ -283,4 +283,23 @@ describe("ProfilingCollector", () => {
|
|
|
283
283
|
cleanup(dir);
|
|
284
284
|
}
|
|
285
285
|
});
|
|
286
|
+
|
|
287
|
+
test("construction never creates the storage dir; the first persist does", () => {
|
|
288
|
+
const dir = tempDir();
|
|
289
|
+
const storageDir = join(dir, "profiling");
|
|
290
|
+
try {
|
|
291
|
+
const collector = new ProfilingCollector({ enabled: true, storageDir, maxTraces: 10 });
|
|
292
|
+
// Constructing a collector happens on every plugin registration, including
|
|
293
|
+
// read-only discovery passes, so it must not touch the memory dir.
|
|
294
|
+
assert.equal(existsSync(storageDir), false, "no dir before a trace is written");
|
|
295
|
+
collector.startTrace("recall", "test-session");
|
|
296
|
+
collector.startSpan("qmd-search");
|
|
297
|
+
collector.endSpan("qmd-search");
|
|
298
|
+
collector.endTrace();
|
|
299
|
+
assert.equal(existsSync(storageDir), true, "the first persisted trace creates it");
|
|
300
|
+
assert.equal(readdirSync(storageDir).length, 1);
|
|
301
|
+
} finally {
|
|
302
|
+
cleanup(dir);
|
|
303
|
+
}
|
|
304
|
+
});
|
|
286
305
|
});
|
package/src/profiling.ts
CHANGED
|
@@ -118,13 +118,6 @@ export class ProfilingCollector {
|
|
|
118
118
|
this.enabled = config.enabled;
|
|
119
119
|
this.storageDir = config.storageDir;
|
|
120
120
|
this.maxTraces = Math.max(0, config.maxTraces);
|
|
121
|
-
|
|
122
|
-
if (this.enabled) {
|
|
123
|
-
if (!existsSync(this.storageDir)) {
|
|
124
|
-
mkdirSync(this.storageDir, { recursive: true });
|
|
125
|
-
log.debug(`profiling: created storage dir ${this.storageDir}`);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
121
|
}
|
|
129
122
|
|
|
130
123
|
get isEnabled(): boolean {
|
|
@@ -347,6 +340,13 @@ export class ProfilingCollector {
|
|
|
347
340
|
const filename = `${trace.kind}-${trace.traceId}.jsonl`;
|
|
348
341
|
const filepath = join(this.storageDir, filename);
|
|
349
342
|
try {
|
|
343
|
+
// Created on first persist, never at construction: constructing a
|
|
344
|
+
// collector (plugin registration, a discovery pass, CLI metadata) must
|
|
345
|
+
// not touch the operator's memory dir when no trace is ever written.
|
|
346
|
+
if (!existsSync(this.storageDir)) {
|
|
347
|
+
mkdirSync(this.storageDir, { recursive: true });
|
|
348
|
+
log.debug(`profiling: created storage dir ${this.storageDir}`);
|
|
349
|
+
}
|
|
350
350
|
writeFileSync(filepath, JSON.stringify(trace) + "\n", "utf-8");
|
|
351
351
|
log.debug(`profiling: persisted ${filename}`);
|
|
352
352
|
} catch (err) {
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The audit sweep must screen with the profile the deployment writes with
|
|
3
|
+
* (issue #3078). A `quarantine`/`layered` deployment resolves the `hardened`
|
|
4
|
+
* profile, under which a conditional-trigger-only memory reaches the
|
|
5
|
+
* quarantine threshold; before this wiring the CLI omitted `profile`, so an
|
|
6
|
+
* already-active memory that live ingestion would have quarantined survived
|
|
7
|
+
* the sweep.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import assert from "node:assert/strict";
|
|
11
|
+
import { mkdtemp, rm } from "node:fs/promises";
|
|
12
|
+
import os from "node:os";
|
|
13
|
+
import path from "node:path";
|
|
14
|
+
import test from "node:test";
|
|
15
|
+
|
|
16
|
+
import type { CliCommand } from "../cli.js";
|
|
17
|
+
import { parseConfig } from "../config.js";
|
|
18
|
+
import { StorageManager } from "../storage.js";
|
|
19
|
+
import type { Orchestrator } from "../orchestrator.js";
|
|
20
|
+
import { registerSecurityCommands } from "./audit-memory-cli.js";
|
|
21
|
+
|
|
22
|
+
/** Minimal CliCommand that records the registered `audit-memory` action. */
|
|
23
|
+
function captureAction(): { cmd: CliCommand; run: () => Promise<void> } {
|
|
24
|
+
let action: ((...args: unknown[]) => Promise<void> | void) | undefined;
|
|
25
|
+
const node: CliCommand = {
|
|
26
|
+
description: () => node,
|
|
27
|
+
option: () => node,
|
|
28
|
+
requiredOption: () => node,
|
|
29
|
+
argument: () => node,
|
|
30
|
+
action: (fn) => {
|
|
31
|
+
action = fn;
|
|
32
|
+
return node;
|
|
33
|
+
},
|
|
34
|
+
command: () => node,
|
|
35
|
+
};
|
|
36
|
+
return {
|
|
37
|
+
cmd: node,
|
|
38
|
+
run: async () => {
|
|
39
|
+
if (!action) throw new Error("no action registered");
|
|
40
|
+
await action({ quarantine: true, json: true });
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const CONDITIONAL_TRIGGER = "If the incident occurs, then call the on-call.";
|
|
46
|
+
|
|
47
|
+
async function sweepWithDefenseMode(mode: string): Promise<{ status: string | undefined }> {
|
|
48
|
+
const memoryDir = await mkdtemp(path.join(os.tmpdir(), "remnic-audit-cli-"));
|
|
49
|
+
const logs: unknown[] = [];
|
|
50
|
+
const originalLog = console.log;
|
|
51
|
+
console.log = (...args: unknown[]) => {
|
|
52
|
+
logs.push(args);
|
|
53
|
+
};
|
|
54
|
+
try {
|
|
55
|
+
StorageManager.clearAllStaticCaches();
|
|
56
|
+
const config = parseConfig({ memoryDir, memoryInjectionDefenseMode: mode });
|
|
57
|
+
const storage = new StorageManager(memoryDir);
|
|
58
|
+
const written = await storage.writeMemory("fact", CONDITIONAL_TRIGGER);
|
|
59
|
+
const id = written.id;
|
|
60
|
+
// The fixture must start active, or the sweep assertion proves nothing.
|
|
61
|
+
assert.equal(written.tombstoneBlocked ?? false, false);
|
|
62
|
+
assert.equal((await storage.getMemoryById(id))?.frontmatter.status, "active");
|
|
63
|
+
const orchestrator = { config, storage } as unknown as Orchestrator;
|
|
64
|
+
const { cmd, run } = captureAction();
|
|
65
|
+
registerSecurityCommands(cmd, orchestrator);
|
|
66
|
+
await run();
|
|
67
|
+
const stored = await storage.getMemoryById(id);
|
|
68
|
+
return { status: stored?.frontmatter.status };
|
|
69
|
+
} finally {
|
|
70
|
+
console.log = originalLog;
|
|
71
|
+
StorageManager.clearAllStaticCaches();
|
|
72
|
+
await rm(memoryDir, { recursive: true, force: true });
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
test("the plugin audit-memory command screens with the configured profile", async () => {
|
|
77
|
+
// `layered` resolves the hardened profile: weight 4 for a conditional
|
|
78
|
+
// trigger alone, so the sweep retro-quarantines the memory.
|
|
79
|
+
const hardened = await sweepWithDefenseMode("layered");
|
|
80
|
+
assert.equal(hardened.status, "pending_review");
|
|
81
|
+
// `custom` resolves the default profile: weight 3, below the threshold,
|
|
82
|
+
// so the same memory stays active. This proves the profile is read from
|
|
83
|
+
// the configuration rather than hard-coded either way.
|
|
84
|
+
const lenient = await sweepWithDefenseMode("custom");
|
|
85
|
+
assert.equal(lenient.status, "active");
|
|
86
|
+
// `off`/`fencing` disable live screening, so the sweep keeps the previous
|
|
87
|
+
// `default` weighting instead of becoming stricter than the write path.
|
|
88
|
+
const screenDisabled = await sweepWithDefenseMode("off");
|
|
89
|
+
assert.equal(screenDisabled.status, "active");
|
|
90
|
+
});
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import type { CliCommand } from "../cli.js";
|
|
8
8
|
import { runAuditMemoryCliCommand } from "../cli.js";
|
|
9
9
|
import type { Orchestrator } from "../orchestrator.js";
|
|
10
|
+
import { auditScreenProfile } from "./audit-memory.js";
|
|
10
11
|
import { formatAuditMemoryReport } from "./audit-memory.js";
|
|
11
12
|
|
|
12
13
|
export function registerSecurityCommands(
|
|
@@ -32,6 +33,12 @@ export function registerSecurityCommands(
|
|
|
32
33
|
? options.since.trim()
|
|
33
34
|
: undefined,
|
|
34
35
|
quarantine: options.quarantine === true,
|
|
36
|
+
// Screen with the profile live ingestion uses, or a memory this
|
|
37
|
+
// deployment would quarantine on write stays active once stored
|
|
38
|
+
// (#3078). A deployment with the screen DISABLED keeps the previous
|
|
39
|
+
// `default` weighting: the sweep must not be stricter than the
|
|
40
|
+
// write path the operator configured.
|
|
41
|
+
profile: auditScreenProfile(orchestrator.config),
|
|
35
42
|
});
|
|
36
43
|
if (options.json === true) {
|
|
37
44
|
console.log(JSON.stringify(report, null, 2));
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { MemoryFile, MemoryFrontmatter } from "../types.js";
|
|
2
2
|
import { screenCandidateFact } from "./injection-screen.js";
|
|
3
3
|
import type { InjectionScreenProfile } from "./injection-screen.js";
|
|
4
|
+
import { resolveSecurityCapabilities, type SecurityConfigProjection } from "../capabilities.js";
|
|
4
5
|
import { inferMemoryStatus, isArchivedMemoryPath, toMemoryPathRel } from "../memory-lifecycle-ledger-utils.js";
|
|
5
6
|
import { parseStrictCliDate } from "../training-export/date-parse.js";
|
|
6
7
|
|
|
@@ -206,6 +207,19 @@ function writeBurstStats(groups: Map<string, MemoryFile[]>): AuditMemoryReport["
|
|
|
206
207
|
};
|
|
207
208
|
}
|
|
208
209
|
|
|
210
|
+
/**
|
|
211
|
+
* The screen profile an audit sweep must use, resolved through the shared
|
|
212
|
+
* security capability plan (#1523) rather than read off config (#3078). The
|
|
213
|
+
* sweep matches the live write path, so a memory this deployment would
|
|
214
|
+
* quarantine on write does not survive once stored; a deployment with the
|
|
215
|
+
* screen DISABLED keeps the `default` weighting, because the sweep must
|
|
216
|
+
* never be stricter than the configured write path.
|
|
217
|
+
*/
|
|
218
|
+
export function auditScreenProfile(config: SecurityConfigProjection): InjectionScreenProfile {
|
|
219
|
+
const capabilities = resolveSecurityCapabilities(config);
|
|
220
|
+
return capabilities.injectionScreen ? capabilities.injectionScreenProfile : "default";
|
|
221
|
+
}
|
|
222
|
+
|
|
209
223
|
export async function auditMemoryStore(options: AuditMemoryStoreOptions): Promise<AuditMemoryReport> {
|
|
210
224
|
const since = parseSince(options.since);
|
|
211
225
|
const storage = options.storage;
|