@sanctuary-framework/mcp-server 0.10.0 → 0.10.1

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/index.cjs CHANGED
@@ -1981,6 +1981,7 @@ var AuditLog = class {
1981
1981
  maxTotalSizeBytes;
1982
1982
  maxEntries;
1983
1983
  rotationInFlight = false;
1984
+ pendingWrites = /* @__PURE__ */ new Set();
1984
1985
  constructor(storage, masterKey, config) {
1985
1986
  this.storage = storage;
1986
1987
  this.encryptionKey = derivePurposeKey(masterKey, "audit-log");
@@ -1989,6 +1990,15 @@ var AuditLog = class {
1989
1990
  }
1990
1991
  /**
1991
1992
  * Append an audit entry.
1993
+ *
1994
+ * The on-disk persist is async and tracked via `pendingWrites`. Long-lived
1995
+ * callers (the main MCP server) can ignore that tracking and let writes
1996
+ * drain naturally. Short-lived callers — the `sanctuary secrets` CLI which
1997
+ * `process.exit()`s immediately after returning from a broker mutation —
1998
+ * MUST await `flush()` before exiting, or in-flight writes get killed
1999
+ * with the event loop and the entry is silently lost. That was the
2000
+ * v0.10.0-rc.2 soak failure mode where `secrets audit` returned empty
2001
+ * after a clean 7-verb lifecycle.
1992
2002
  */
1993
2003
  append(layer, operation, identityId, details, result = "success") {
1994
2004
  const entry = {
@@ -2000,8 +2010,22 @@ var AuditLog = class {
2000
2010
  details
2001
2011
  };
2002
2012
  this.entries.push(entry);
2003
- this.persistEntry(entry).catch(() => {
2013
+ const writePromise = this.persistEntry(entry).catch(() => {
2004
2014
  });
2015
+ this.pendingWrites.add(writePromise);
2016
+ void writePromise.finally(() => this.pendingWrites.delete(writePromise));
2017
+ }
2018
+ /**
2019
+ * Wait for every in-flight `append()` persist (and its rotation pass) to
2020
+ * settle. Safe to call multiple times — newly-appended entries during a
2021
+ * flush are also awaited. Re-entrant only at the granularity of "drain
2022
+ * everything queued so far". Short-lived CLIs MUST call this before
2023
+ * `process.exit()` to keep audit writes durable.
2024
+ */
2025
+ async flush() {
2026
+ while (this.pendingWrites.size > 0) {
2027
+ await Promise.allSettled([...this.pendingWrites]);
2028
+ }
2005
2029
  }
2006
2030
  async persistEntry(entry) {
2007
2031
  const key = `${Date.now()}-${this.counter++}`;
@@ -2012,7 +2036,7 @@ var AuditLog = class {
2012
2036
  key,
2013
2037
  stringToBytes(JSON.stringify(encrypted))
2014
2038
  );
2015
- this.maybeRotate().catch(() => {
2039
+ await this.maybeRotate().catch(() => {
2016
2040
  });
2017
2041
  }
2018
2042
  /**