@osovv/vv-opencode 0.2.4 → 0.3.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 (56) hide show
  1. package/README.md +37 -19
  2. package/dist/cli.js +21 -0
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/doctor.js +20 -0
  5. package/dist/commands/doctor.js.map +1 -1
  6. package/dist/commands/guardian.js +22 -0
  7. package/dist/commands/guardian.js.map +1 -1
  8. package/dist/commands/install.js +20 -0
  9. package/dist/commands/install.js.map +1 -1
  10. package/dist/commands/status.js +20 -0
  11. package/dist/commands/status.js.map +1 -1
  12. package/dist/commands/sync.js +20 -0
  13. package/dist/commands/sync.js.map +1 -1
  14. package/dist/commands/version.js +18 -0
  15. package/dist/commands/version.js.map +1 -1
  16. package/dist/index.d.ts +1 -0
  17. package/dist/index.js +19 -0
  18. package/dist/index.js.map +1 -1
  19. package/dist/lib/opencode.js +53 -0
  20. package/dist/lib/opencode.js.map +1 -1
  21. package/dist/lib/package.js +22 -0
  22. package/dist/lib/package.js.map +1 -1
  23. package/dist/lib/vvoc-paths.js +26 -0
  24. package/dist/lib/vvoc-paths.js.map +1 -1
  25. package/dist/plugins/guardian.js +42 -0
  26. package/dist/plugins/guardian.js.map +1 -1
  27. package/dist/plugins/memory-store.d.ts +2 -1
  28. package/dist/plugins/memory-store.js +78 -7
  29. package/dist/plugins/memory-store.js.map +1 -1
  30. package/dist/plugins/memory.js +43 -5
  31. package/dist/plugins/memory.js.map +1 -1
  32. package/dist/plugins/secrets-redaction/config.d.ts +26 -0
  33. package/dist/plugins/secrets-redaction/config.js +158 -0
  34. package/dist/plugins/secrets-redaction/config.js.map +1 -0
  35. package/dist/plugins/secrets-redaction/deep.d.ts +4 -0
  36. package/dist/plugins/secrets-redaction/deep.js +78 -0
  37. package/dist/plugins/secrets-redaction/deep.js.map +1 -0
  38. package/dist/plugins/secrets-redaction/engine.d.ts +14 -0
  39. package/dist/plugins/secrets-redaction/engine.js +113 -0
  40. package/dist/plugins/secrets-redaction/engine.js.map +1 -0
  41. package/dist/plugins/secrets-redaction/index.d.ts +2 -0
  42. package/dist/plugins/secrets-redaction/index.js +124 -0
  43. package/dist/plugins/secrets-redaction/index.js.map +1 -0
  44. package/dist/plugins/secrets-redaction/patterns.d.ts +26 -0
  45. package/dist/plugins/secrets-redaction/patterns.js +85 -0
  46. package/dist/plugins/secrets-redaction/patterns.js.map +1 -0
  47. package/dist/plugins/secrets-redaction/restore.d.ts +2 -0
  48. package/dist/plugins/secrets-redaction/restore.js +25 -0
  49. package/dist/plugins/secrets-redaction/restore.js.map +1 -0
  50. package/dist/plugins/secrets-redaction/session.d.ts +30 -0
  51. package/dist/plugins/secrets-redaction/session.js +113 -0
  52. package/dist/plugins/secrets-redaction/session.js.map +1 -0
  53. package/dist/plugins/secrets-redaction.d.ts +1 -0
  54. package/dist/plugins/secrets-redaction.js +16 -0
  55. package/dist/plugins/secrets-redaction.js.map +1 -0
  56. package/package.json +5 -2
@@ -0,0 +1,25 @@
1
+ // FILE: src/plugins/secrets-redaction/restore.ts
2
+ // VERSION: 1.0.0
3
+ // START_MODULE_CONTRACT
4
+ // PURPOSE: Restores placeholders in a single string back to original secret values.
5
+ // SCOPE: single-string placeholder → original lookup
6
+ // DEPENDS: session
7
+ // LINKS: knowledge-graph://plugins/secrets-redaction
8
+ // ROLE: RUNTIME
9
+ // MAP_MODE: EXPORTS
10
+ // END_MODULE_CONTRACT
11
+ //
12
+ // START_MODULE_MAP
13
+ // restoreText - restores all placeholders in a string to original values
14
+ // END_MODULE_MAP
15
+ import { getPlaceholderRegex } from "./session.js";
16
+ export function restoreText(input, session) {
17
+ if (!input)
18
+ return input;
19
+ const regex = getPlaceholderRegex(session["prefix"]);
20
+ return input.replace(regex, (placeholder) => {
21
+ const original = session.lookup(placeholder);
22
+ return original ?? placeholder;
23
+ });
24
+ }
25
+ //# sourceMappingURL=restore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"restore.js","sourceRoot":"","sources":["../../../src/plugins/secrets-redaction/restore.ts"],"names":[],"mappings":"AAAA,iDAAiD;AACjD,iBAAiB;AACjB,wBAAwB;AACxB,sFAAsF;AACtF,uDAAuD;AACvD,qBAAqB;AACrB,uDAAuD;AACvD,kBAAkB;AAClB,sBAAsB;AACtB,sBAAsB;AACtB,EAAE;AACF,mBAAmB;AACnB,2EAA2E;AAC3E,iBAAiB;AAGjB,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEnD,MAAM,UAAU,WAAW,CAAC,KAAa,EAAE,OAA2B;IACpE,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IAEzB,MAAM,KAAK,GAAG,mBAAmB,CAAC,OAAO,CAAC,QAAQ,CAAsB,CAAC,CAAC;IAC1E,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,EAAE;QAC1C,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAC7C,OAAO,QAAQ,IAAI,WAAW,CAAC;IACjC,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,30 @@
1
+ export interface PlaceholderSessionOptions {
2
+ prefix: string;
3
+ ttlMs: number;
4
+ maxMappings: number;
5
+ secret: string;
6
+ }
7
+ export interface PlaceholderEntry {
8
+ original: string;
9
+ placeholder: string;
10
+ category: string;
11
+ createdAt: number;
12
+ }
13
+ export declare class PlaceholderSession {
14
+ private readonly prefix;
15
+ private readonly ttlMs;
16
+ private readonly maxMappings;
17
+ private readonly secret;
18
+ private readonly forward;
19
+ private readonly reverse;
20
+ private readonly created;
21
+ constructor(options: PlaceholderSessionOptions);
22
+ private computeHash;
23
+ getOrCreatePlaceholder(original: string, category: string): string;
24
+ lookup(placeholder: string): string | undefined;
25
+ cleanup(now: number): number;
26
+ private evictIfNeeded;
27
+ get size(): number;
28
+ }
29
+ export declare function getPlaceholderRegex(prefix: string): RegExp;
30
+ export declare function generateFallbackSecret(): string;
@@ -0,0 +1,113 @@
1
+ // FILE: src/plugins/secrets-redaction/session.ts
2
+ // VERSION: 1.0.0
3
+ // START_MODULE_CONTRACT
4
+ // PURPOSE: Manages placeholder lifecycle for secret redaction — generates stable HMAC-based placeholders,
5
+ // maintains forward/reverse mappings, handles TTL eviction and max-mappings limits.
6
+ // SCOPE: placeholder creation, lookup, cleanup
7
+ // DEPENDS: node:crypto
8
+ // LINKS: knowledge-graph://plugins/secrets-redaction
9
+ // ROLE: RUNTIME
10
+ // MAP_MODE: EXPORTS
11
+ // END_MODULE_CONTRACT
12
+ //
13
+ // START_MODULE_MAP
14
+ // PlaceholderSession - manages secret → placeholder mappings with HMAC hashing
15
+ // getPlaceholderRegex - returns RegExp to find all placeholders in text
16
+ // END_MODULE_MAP
17
+ import { createHmac, randomBytes } from "node:crypto";
18
+ export class PlaceholderSession {
19
+ prefix;
20
+ ttlMs;
21
+ maxMappings;
22
+ secret;
23
+ forward = new Map();
24
+ reverse = new Map();
25
+ created = new Map();
26
+ constructor(options) {
27
+ this.prefix = options.prefix;
28
+ this.ttlMs = options.ttlMs;
29
+ this.maxMappings = options.maxMappings;
30
+ this.secret = Buffer.from(options.secret, "utf-8");
31
+ }
32
+ computeHash(original) {
33
+ return createHmac("sha256", this.secret).update(original, "utf-8").digest("hex");
34
+ }
35
+ getOrCreatePlaceholder(original, category) {
36
+ if (this.reverse.has(original)) {
37
+ return this.reverse.get(original);
38
+ }
39
+ this.evictIfNeeded();
40
+ const hash = this.computeHash(original);
41
+ const hash12 = hash.substring(0, 12);
42
+ let placeholder = `${this.prefix}${category}_${hash12}__`;
43
+ if (this.forward.has(placeholder)) {
44
+ let counter = 1;
45
+ while (this.forward.has(placeholder)) {
46
+ placeholder = `${this.prefix}${category}_${hash12}_${counter}__`;
47
+ counter++;
48
+ }
49
+ }
50
+ const entry = {
51
+ original,
52
+ placeholder,
53
+ category,
54
+ createdAt: Date.now(),
55
+ };
56
+ this.forward.set(placeholder, entry);
57
+ this.reverse.set(original, placeholder);
58
+ this.created.set(placeholder, Date.now());
59
+ return placeholder;
60
+ }
61
+ lookup(placeholder) {
62
+ return this.forward.get(placeholder)?.original;
63
+ }
64
+ cleanup(now) {
65
+ let evicted = 0;
66
+ const expired = [];
67
+ for (const [placeholder, createdAt] of this.created) {
68
+ if (now - createdAt > this.ttlMs) {
69
+ expired.push(placeholder);
70
+ }
71
+ }
72
+ for (const placeholder of expired) {
73
+ const entry = this.forward.get(placeholder);
74
+ if (entry) {
75
+ this.reverse.delete(entry.original);
76
+ this.forward.delete(placeholder);
77
+ this.created.delete(placeholder);
78
+ evicted++;
79
+ }
80
+ }
81
+ return evicted;
82
+ }
83
+ evictIfNeeded() {
84
+ if (this.forward.size < this.maxMappings)
85
+ return;
86
+ let oldestPlaceholder = null;
87
+ let oldestCreated = Infinity;
88
+ for (const [placeholder, createdAt] of this.created) {
89
+ if (createdAt < oldestCreated) {
90
+ oldestCreated = createdAt;
91
+ oldestPlaceholder = placeholder;
92
+ }
93
+ }
94
+ if (oldestPlaceholder) {
95
+ const entry = this.forward.get(oldestPlaceholder);
96
+ if (entry) {
97
+ this.reverse.delete(entry.original);
98
+ this.forward.delete(oldestPlaceholder);
99
+ this.created.delete(oldestPlaceholder);
100
+ }
101
+ }
102
+ }
103
+ get size() {
104
+ return this.forward.size;
105
+ }
106
+ }
107
+ export function getPlaceholderRegex(prefix) {
108
+ return new RegExp(`${prefix}[A-Z_]+_[0-9a-f]{12}(?:_\\d+)?__`, "g");
109
+ }
110
+ export function generateFallbackSecret() {
111
+ return randomBytes(32).toString("hex");
112
+ }
113
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../../src/plugins/secrets-redaction/session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export { SecretsRedactionPlugin } from "./secrets-redaction/index.js";
@@ -0,0 +1,16 @@
1
+ // FILE: src/plugins/secrets-redaction.ts
2
+ // VERSION: 1.0.0
3
+ // START_MODULE_CONTRACT
4
+ // PURPOSE: Re-export barrel for SecretsRedactionPlugin
5
+ // SCOPE: plugin re-exports
6
+ // DEPENDS: secrets-redaction/index
7
+ // LINKS: knowledge-graph://plugins/secrets-redaction
8
+ // ROLE: BARREL
9
+ // MAP_MODE: SUMMARY
10
+ // END_MODULE_CONTRACT
11
+ //
12
+ // START_MODULE_MAP
13
+ // SecretsRedactionPlugin - main plugin export
14
+ // END_MODULE_MAP
15
+ export { SecretsRedactionPlugin } from "./secrets-redaction/index.js";
16
+ //# sourceMappingURL=secrets-redaction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secrets-redaction.js","sourceRoot":"","sources":["../../src/plugins/secrets-redaction.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,iBAAiB;AACjB,wBAAwB;AACxB,yDAAyD;AACzD,6BAA6B;AAC7B,qCAAqC;AACrC,uDAAuD;AACvD,iBAAiB;AACjB,sBAAsB;AACtB,sBAAsB;AACtB,EAAE;AACF,mBAAmB;AACnB,gDAAgD;AAChD,iBAAiB;AAEjB,OAAO,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@osovv/vv-opencode",
3
- "version": "0.2.4",
4
- "description": "Portable OpenCode workflow plugins and CLI tooling.",
3
+ "version": "0.3.0",
4
+ "description": "Portable OpenCode workflow plugins, explicit memory, and CLI tooling.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
@@ -15,6 +15,8 @@
15
15
  "workflow",
16
16
  "guardian",
17
17
  "memory",
18
+ "xdg",
19
+ "grace",
18
20
  "bun",
19
21
  "citty"
20
22
  ],
@@ -47,6 +49,7 @@
47
49
  "fmt:check": "oxfmt --check src",
48
50
  "test": "bun test",
49
51
  "check": "bun run typecheck && bun run lint && bun run fmt:check && bun test",
52
+ "pack:check": "npm pack --dry-run",
50
53
  "prepare": "lefthook install --force"
51
54
  },
52
55
  "dependencies": {