@securecoms/agent-bridge 0.9.0 → 0.11.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.
@@ -674,6 +674,58 @@ export declare class BridgeAgent {
674
674
  * the other enclaves in the set.
675
675
  */
676
676
  private refreshChannelMeta;
677
+ /** Cache for the server-side enclave enumeration (see enclavesToCover). */
678
+ private enclaveEnumCache;
679
+ /** Enclaves whose channel listing failed on the NEWEST sweep (audit HIGH:
680
+ * skip-one deleted the sweep's partial-coverage signal — observations_stale
681
+ * is a global max, so one healthy enclave masked a failed one). Surfaced on
682
+ * health() so partial coverage is never silent. */
683
+ private sweepEnclavesFailed;
684
+ /** Enclave ids whose channel listing has EVER succeeded this process, seeded
685
+ * with HOME (home is always expected to list; without the seed, a home
686
+ * failure right after a restart would read as "never succeeded" and slip
687
+ * through the expected-gap branch — weaker than the old abort-on-failure).
688
+ * A failure of a member of this set is a REGRESSION and degrades health; a
689
+ * failure of a never-succeeded enclave (partner: tenant-scoped 404, permanent
690
+ * pending backend authz) is an EXPECTED gap — reported, not degrading, or
691
+ * every federated agent would peg degraded forever. */
692
+ private readonly enclaveListEverSucceeded;
693
+ /** Warn-once-per-failure-streak, keyed by enclave id (cleared on success):
694
+ * a permanently-404ing partner enclave must not log 1440 lines a day. */
695
+ private readonly enclaveListWarned;
696
+ private static readonly ENCLAVE_ENUM_TTL_MS;
697
+ private enclaveEnumWarned;
698
+ /**
699
+ * C1 (split-brain Task 3): every enclave this agent must COVER — for the
700
+ * self-heal sweep and for channel-meta refresh alike. ONE helper on purpose:
701
+ * these two call sites had drifted (refreshChannelMeta looped home+learned,
702
+ * selfHealSweep looped nothing), and the drift is exactly what left both
703
+ * production agents with zero recovery coverage in their second enclave.
704
+ *
705
+ * The set is SERVER enumeration ∪ home ∪ store-learned:
706
+ *
707
+ * - SERVER (`GET /api/v1/enclaves`, membership-scoped, federated included)
708
+ * is the authoritative source. The store CANNOT be: channel_meta's only
709
+ * writers are listChannels itself (circular — you learn enclave B by
710
+ * having already listed B) and the receive pump's successfully-decrypted
711
+ * loop, and a FORKED agent decrypts nothing, so the agent that most needs
712
+ * sweeping in enclave B is precisely the one whose store never learned B.
713
+ * - home + learned stay in the union as the degraded-mode floor: if the
714
+ * enumeration endpoint is down, we sweep what we can rather than nothing,
715
+ * and we warn (once) so the gap is diagnosable.
716
+ *
717
+ * The server result is cached for ENCLAVE_ENUM_TTL_MS so per-ingest-cycle
718
+ * callers (refreshChannelMeta) do not add an HTTP round-trip per cycle;
719
+ * membership changes are picked up within one TTL, which matches the sweep
720
+ * cadence this exists to serve.
721
+ *
722
+ * ⚠️ Residual gap, stated: the enumeration RETURNS cross-tenant partner
723
+ * enclaves, but `list_channels_in_enclave` is tenant-scoped and 404s them
724
+ * under this agent's bearer — so a partner enclave in this set still yields
725
+ * no channels. Callers must treat a per-enclave listing failure as skip-one,
726
+ * never abort-all. Closing that needs backend authz work, not daemon work.
727
+ */
728
+ private enclavesToCover;
677
729
  /** A live roster for a channel, or undefined if missing OR expired past the TTL. */
678
730
  private freshRoster;
679
731
  /**
@@ -799,6 +851,12 @@ export declare class BridgeAgent {
799
851
  rate_limited: number;
800
852
  /** Cumulative inbound rows acked-and-dropped because they were provably past-epoch undecryptable (forward-secrecy secret gone). */
801
853
  permanently_skipped: number;
854
+ /** SDK-6: cumulative rows ack-drained via QUARANTINE, distinct from the
855
+ * same-group past-epoch permanently_skipped drain. */
856
+ quarantine_drained: number;
857
+ /** SDK-6: cumulative rows ack-drained because their group_id is RETIRED for
858
+ * the channel (superseded fork-loser traffic). */
859
+ retired_drained: number;
802
860
  /** Track 5: cumulative artifact_share messages where download/decrypt/digest failed (fail-soft — acked, no redeliver). */
803
861
  failed_attachments: number;
804
862
  /** 2026-07-03 latency triage: delivery pings received on the WS stream.
@@ -836,6 +894,12 @@ export declare class BridgeAgent {
836
894
  degraded: boolean;
837
895
  /** M6: per-channel observations, newest sweep. Read from cache; no I/O. */
838
896
  channels: ChannelObservation[];
897
+ /** C1: enclaves whose channel listing failed on the newest sweep. Non-empty
898
+ * means partial coverage — those enclaves' channels were NOT probed. A
899
+ * PREVIOUSLY-SUCCEEDING (or home) entry also flips `degraded`; a
900
+ * never-succeeded entry (partner enclave, tenant-scoped 404) is reported
901
+ * here without degrading. */
902
+ sweep_enclaves_failed: string[];
839
903
  /** Optional memory-adapter counters (e.g. Hermes provider); present only when the active provider exposes stats(). */
840
904
  hermes_no_session?: number;
841
905
  hermes_skipped?: number;
@@ -882,9 +946,19 @@ export declare class BridgeAgent {
882
946
  filteredRoomMessages: number;
883
947
  rateLimitedSends: number;
884
948
  permanentlySkipped: number;
949
+ /** SDK-6: cumulative rows ack-drained via QUARANTINE, distinct from the
950
+ * same-group past-epoch permanentlySkipped drain. */
951
+ quarantineDrained: number;
952
+ /** SDK-6: cumulative rows ack-drained because their group_id is RETIRED for
953
+ * the channel (superseded fork-loser traffic). */
954
+ retiredDrained: number;
885
955
  welcomeRequestsSent: number;
886
956
  /** Track 5: cumulative artifact_share failures (download/decrypt/digest). */
887
957
  failedAttachments: number;
958
+ /** SDK-6: bridge build id, so a /v1/metrics reading captured across a daemon
959
+ * restart can be attributed to a version — counters are process-lifetime
960
+ * and zero on restart (spec §5.5). */
961
+ build: string;
888
962
  };
889
963
  close(): Promise<void>;
890
964
  }