@forgezero/agent 0.1.25 → 0.1.26

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/fz-agent.js CHANGED
@@ -25,30 +25,44 @@ class CacheError extends Error {
25
25
  var DEFAULT_TTL_MS = 60000;
26
26
  var DEFAULT_MAX_STALE_MS = 300000;
27
27
  function createSecretCache(options) {
28
- const entries = new Map;
28
+ let entries = new Map;
29
29
  const now = options.now ?? (() => Date.now());
30
30
  const ttlMs = options.ttlMs ?? DEFAULT_TTL_MS;
31
31
  const maxStaleMs = options.maxStaleMs ?? DEFAULT_MAX_STALE_MS;
32
32
  let cursor = 0;
33
33
  let replicated = false;
34
34
  let lastSyncOkMs = now();
35
- const loadScope = async () => {
35
+ const fetchScope = async () => {
36
+ const next = new Map;
36
37
  if (!options.list)
37
- return { loaded: 0, failed: [] };
38
+ return { entries: next, loaded: 0, failed: [] };
38
39
  const names = await options.list();
39
40
  const failed = [];
40
- let loaded = 0;
41
41
  for (const name of names) {
42
42
  try {
43
43
  const result = await options.fetch(name);
44
- entries.set(name, { value: result.value, version: result.version, fetchedAtMs: now() });
45
- loaded += 1;
44
+ next.set(name, { value: result.value, version: result.version, fetchedAtMs: now() });
46
45
  } catch {
47
46
  failed.push(name);
48
47
  }
49
48
  }
49
+ return { entries: next, loaded: next.size, failed };
50
+ };
51
+ const loadScope = async () => {
52
+ if (!options.list)
53
+ return { loaded: 0, failed: [] };
54
+ const snapshot = await fetchScope();
55
+ entries = snapshot.entries;
56
+ replicated = snapshot.failed.length === 0;
57
+ return { loaded: snapshot.loaded, failed: snapshot.failed };
58
+ };
59
+ const refreshScope = async () => {
60
+ const snapshot = await fetchScope();
61
+ if (snapshot.failed.length > 0) {
62
+ throw new CacheError("FETCH_FAILED", `Could not refresh ${snapshot.failed.length} assigned vault ${snapshot.failed.length === 1 ? "entry" : "entries"}.`);
63
+ }
64
+ entries = snapshot.entries;
50
65
  replicated = true;
51
- return { loaded, failed };
52
66
  };
53
67
  return {
54
68
  names: () => [...entries.keys()],
@@ -82,13 +96,26 @@ function createSecretCache(options) {
82
96
  const result = await options.changes(cursor);
83
97
  if (result.resync) {
84
98
  const dropped = [...entries.keys()];
85
- entries.clear();
99
+ if (options.list) {
100
+ await refreshScope();
101
+ } else {
102
+ entries.clear();
103
+ }
86
104
  cursor = 0;
87
105
  lastSyncOkMs = now();
88
- if (options.list)
89
- await loadScope();
90
106
  return { invalidated: dropped, cursor: 0, resync: true };
91
107
  }
108
+ if (options.list && result.changed.length > 0) {
109
+ const held = new Set(entries.keys());
110
+ await refreshScope();
111
+ cursor = result.version;
112
+ lastSyncOkMs = now();
113
+ return {
114
+ invalidated: result.changed.filter((name) => held.has(name) || entries.has(name)),
115
+ cursor,
116
+ resync: false
117
+ };
118
+ }
92
119
  const invalidated = [];
93
120
  for (const name of result.changed) {
94
121
  if (entries.delete(name))
@@ -2955,7 +2982,7 @@ function materializeWarpMdm(options) {
2955
2982
  }
2956
2983
 
2957
2984
  // src/version.ts
2958
- var VERSION = "0.1.25";
2985
+ var VERSION = "0.1.26";
2959
2986
 
2960
2987
  // src/index.ts
2961
2988
  function loadOrCreateSeed(path) {
package/dist/fz.js CHANGED
@@ -974,7 +974,7 @@ async function resolveIdentity(selector, socketPath) {
974
974
  }
975
975
 
976
976
  // src/version.ts
977
- var VERSION = "0.1.25";
977
+ var VERSION = "0.1.26";
978
978
 
979
979
  // src/cli/index.ts
980
980
  var DEFAULT_MODE = THRESHOLD_MODES[0].id;
@@ -10,30 +10,44 @@ class CacheError extends Error {
10
10
  var DEFAULT_TTL_MS = 60000;
11
11
  var DEFAULT_MAX_STALE_MS = 300000;
12
12
  function createSecretCache(options) {
13
- const entries = new Map;
13
+ let entries = new Map;
14
14
  const now = options.now ?? (() => Date.now());
15
15
  const ttlMs = options.ttlMs ?? DEFAULT_TTL_MS;
16
16
  const maxStaleMs = options.maxStaleMs ?? DEFAULT_MAX_STALE_MS;
17
17
  let cursor = 0;
18
18
  let replicated = false;
19
19
  let lastSyncOkMs = now();
20
- const loadScope = async () => {
20
+ const fetchScope = async () => {
21
+ const next = new Map;
21
22
  if (!options.list)
22
- return { loaded: 0, failed: [] };
23
+ return { entries: next, loaded: 0, failed: [] };
23
24
  const names = await options.list();
24
25
  const failed = [];
25
- let loaded = 0;
26
26
  for (const name of names) {
27
27
  try {
28
28
  const result = await options.fetch(name);
29
- entries.set(name, { value: result.value, version: result.version, fetchedAtMs: now() });
30
- loaded += 1;
29
+ next.set(name, { value: result.value, version: result.version, fetchedAtMs: now() });
31
30
  } catch {
32
31
  failed.push(name);
33
32
  }
34
33
  }
34
+ return { entries: next, loaded: next.size, failed };
35
+ };
36
+ const loadScope = async () => {
37
+ if (!options.list)
38
+ return { loaded: 0, failed: [] };
39
+ const snapshot = await fetchScope();
40
+ entries = snapshot.entries;
41
+ replicated = snapshot.failed.length === 0;
42
+ return { loaded: snapshot.loaded, failed: snapshot.failed };
43
+ };
44
+ const refreshScope = async () => {
45
+ const snapshot = await fetchScope();
46
+ if (snapshot.failed.length > 0) {
47
+ throw new CacheError("FETCH_FAILED", `Could not refresh ${snapshot.failed.length} assigned vault ${snapshot.failed.length === 1 ? "entry" : "entries"}.`);
48
+ }
49
+ entries = snapshot.entries;
35
50
  replicated = true;
36
- return { loaded, failed };
37
51
  };
38
52
  return {
39
53
  names: () => [...entries.keys()],
@@ -67,13 +81,26 @@ function createSecretCache(options) {
67
81
  const result = await options.changes(cursor);
68
82
  if (result.resync) {
69
83
  const dropped = [...entries.keys()];
70
- entries.clear();
84
+ if (options.list) {
85
+ await refreshScope();
86
+ } else {
87
+ entries.clear();
88
+ }
71
89
  cursor = 0;
72
90
  lastSyncOkMs = now();
73
- if (options.list)
74
- await loadScope();
75
91
  return { invalidated: dropped, cursor: 0, resync: true };
76
92
  }
93
+ if (options.list && result.changed.length > 0) {
94
+ const held = new Set(entries.keys());
95
+ await refreshScope();
96
+ cursor = result.version;
97
+ lastSyncOkMs = now();
98
+ return {
99
+ invalidated: result.changed.filter((name) => held.has(name) || entries.has(name)),
100
+ cursor,
101
+ resync: false
102
+ };
103
+ }
77
104
  const invalidated = [];
78
105
  for (const name of result.changed) {
79
106
  if (entries.delete(name))
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  /** One package version shared by both public binaries. Pinned to package.json by tests. */
2
- export declare const VERSION = "0.1.25";
2
+ export declare const VERSION = "0.1.26";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "//": "Publishing happens from an operator's machine, not CI \u2014 CLAUDE.md records that the absence of CI is deliberate. npm's `provenance` attests a tarball was built by a recognised CI provider from a named commit, so it cannot be produced here: it was set, and the first publish failed with `Automatic provenance generation not supported for provider: null`. A setting that can never be satisfied is worse than none, because it reads as a guarantee nobody is getting. Restore it the day this publishes from CI, and not before.",
3
3
  "name": "@forgezero/agent",
4
- "version": "0.1.25",
4
+ "version": "0.1.26",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "check": "tsc --noEmit",