@cotal-ai/auth 0.67.0 → 0.68.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.
package/dist/service.js CHANGED
@@ -57,9 +57,9 @@ import { createHash, randomBytes } from "node:crypto";
57
57
  import { createServer } from "node:http";
58
58
  import { resolve } from "node:path";
59
59
  import { connect, credsAuthenticator } from "@nats-io/transport-node";
60
- import { jetstreamManager } from "@nats-io/jetstream";
60
+ import { jetstream, jetstreamManager } from "@nats-io/jetstream";
61
61
  import { Kvm } from "@nats-io/kv";
62
- import { CotalEndpoint, deprovisionAgent, isConcreteChannel, provisionAgentDurables, contractDigest, contractRefToHex, contractStoreContext, endpointToken, fetchContractArtifact, verifyClusterManifest, verifyClusterRoot, admissionBucket, admissionMediatorGrants, assertDerivedOwnerToken, assertLifecycleToken, assertValidOwnerToken, authorizeTrustedServeSnapshot, commitSiblingIssuance, credsClaims, EpEnvelopeError, ensureAuthorityStores, epAuthBucket, isReachable, jwtFromCreds, managedRetirementOpId, mintCreds, mintPublicUserJwt, newIdentity, observeHostedRunAttempt, openRecordsBucket, parseEndpointGate, parseServiceSpec, parseServiceStatus, rawDigest, parseSecretStoreIdentity, readCheckpointStatus, readRunAdmission, readRunRecord, readSvcRecordLeader, reconcileEndpointGate, sameSecretStoreIdentity, recordSpecKey, recordStatusKey, RECORD_KINDS, recordsBucket, remoteManagerActors, retirementFrontierStreams, runDriverCaller, serveIssuanceGateKv, standaloneConnectOpts, STANDING_RENEWABLE_TTL_SEC, withIssuerSession, acceptedReadGrant, actorLedgerSource, connectionAcceptedToken, importNativeSubjectPermissions, mintGeneration, parseActorLedgerSource, writeAcceptedRow, invokeCommand, resolveService, contractArtifactCanonicalBytes, DEV_OWNER, endpointRegistrationBarrier, mintLifecycleUid, principalKey, provisionEndpointGateOpen, publishContractArtifact, registerServiceInstance, registerServingInstance } from "@cotal-ai/core";
62
+ import { CotalEndpoint, deprovisionAgent, isConcreteChannel, provisionAgentDurables, contractDigest, contractRefToHex, contractStoreContext, endpointToken, fetchContractArtifact, verifyClusterManifest, verifyClusterRoot, admissionBucket, admissionMediatorGrants, assertDerivedOwnerToken, assertLifecycleToken, assertValidOwnerToken, authorizeTrustedServeSnapshot, commitSiblingIssuance, credsClaims, EpEnvelopeError, ensureAuthorityStores, epAuthBucket, isReachable, jwtFromCreds, managedRetirementOpId, mintCreds, mintPublicUserJwt, newIdentity, newTakeoverId, observeHostedRunAttempt, openRecordsBucket, parseEndpointGate, parseServiceSpec, parseServiceStatus, rawDigest, parseSecretStoreIdentity, readCheckpointStatus, readRunAdmission, readRunRecord, readSvcRecordLeader, reconcileEndpointGate, replayRunJournal, sameSecretStoreIdentity, recordSpecKey, recordStatusKey, RECORD_KINDS, recordsBucket, remoteManagerActors, retirementFrontierStreams, runDriverCaller, serveIssuanceGateKv, standaloneConnectOpts, STANDING_RENEWABLE_TTL_SEC, withIssuerSession, acceptedReadGrant, actorLedgerSource, connectionAcceptedToken, importNativeSubjectPermissions, mintGeneration, parseActorLedgerSource, writeAcceptedRow, invokeCommand, resolveService, contractArtifactCanonicalBytes, DEV_OWNER, endpointRegistrationBarrier, mintLifecycleUid, principalKey, provisionEndpointGateOpen, publishContractArtifact, registerServiceInstance, registerServingInstance } from "@cotal-ai/core";
63
63
  import { findCotalRoot, loadManagerInstanceIdentity, userAuthStateDir, workspaceSecretStore, createAuthInstanceIdentity, loadAuthInstanceIdentity } from "@cotal-ai/workspace";
64
64
  import { decodeJwt } from "jose";
65
65
  import { deriveOwnerForIdpSubject, platformControlOwner } from "./derive.js";
@@ -447,6 +447,9 @@ export async function openAuthAuthorityPlane(opts) {
447
447
  }
448
448
  const fileArm = ledgerAuthorizeConnect(opts.dir);
449
449
  const recordsJsm = await jetstreamManager(remoteIssuer.nc);
450
+ const authKv = await new Kvm(remoteIssuer.nc).open(epAuthBucket(space));
451
+ const managerIssuanceGate = (instanceId) => serveIssuanceGateKv(authKv, space, { endpoint: "manager", instanceId });
452
+ const observeManagerGate = async (instanceId) => managerIssuanceGate(instanceId).observe();
450
453
  const loadLocalManager = opts.localManager ?? (() => undefined);
451
454
  // Standing renewal and a served resume or answer read the manager surface from the REGISTERED
452
455
  // service spec at the gate's registration revision: spec (leader read) -> closure manifest -> root
@@ -475,7 +478,7 @@ export async function openAuthAuthorityPlane(opts) {
475
478
  };
476
479
  const managerGate = async (owner, instanceId) => {
477
480
  const localManager = loadLocalManager();
478
- const gate = await serveIssuanceGateKv(await new Kvm(remoteIssuer.nc).open(epAuthBucket(space)), space, { endpoint: "manager", instanceId }).observe();
481
+ const gate = await observeManagerGate(instanceId);
479
482
  if (!gate)
480
483
  return "unknown";
481
484
  if (gate.state !== "open")
@@ -590,7 +593,6 @@ export async function openAuthAuthorityPlane(opts) {
590
593
  observedRunRequests.delete(subject);
591
594
  return observed !== undefined && observed.expires > Date.now() ? observed.request : undefined;
592
595
  };
593
- const observeManagerGate = async (instanceId) => serveIssuanceGateKv(await new Kvm(remoteIssuer.nc).open(epAuthBucket(space)), space, { endpoint: "manager", instanceId }).observe();
594
596
  // A managed lifecycle's broker footprint, released under a deprovisioner pinned to that uid, so
595
597
  // no call here can reach a same-name successor's durables.
596
598
  const deprovisionManagedFootprint = async (owner, actor, lifecycleUid, memberChannels) => {
@@ -656,7 +658,7 @@ export async function openAuthAuthorityPlane(opts) {
656
658
  space,
657
659
  managerGate: async (owner, instanceId) => {
658
660
  const verdict = await managerGate(owner, assertLifecycleToken(instanceId, "serving.instanceId"));
659
- const gate = await serveIssuanceGateKv(await new Kvm(remoteIssuer.nc).open(epAuthBucket(space)), space, { endpoint: "manager", instanceId }).observe();
661
+ const gate = await observeManagerGate(instanceId);
660
662
  return { verdict, ...(gate ? { processEpoch: gate.processEpoch } : {}) };
661
663
  },
662
664
  }, principal, claim);
@@ -731,7 +733,6 @@ export async function openAuthAuthorityPlane(opts) {
731
733
  issueManagerServiceAuthority: async (holder) => {
732
734
  refuseIfFenced();
733
735
  const { owner } = holder;
734
- const observeManagerGate = async (instanceId) => (await serveIssuanceGateKv(await new Kvm(remoteIssuer.nc).open(epAuthBucket(space)), space, { endpoint: "manager", instanceId }).observe()) ?? null;
735
736
  return issueRemoteManagerAuthority({
736
737
  ...holder,
737
738
  authorizeRenewal: ({ owner: o, request: r }) => authorizeRemoteManagerRenewal({
@@ -746,7 +747,8 @@ export async function openAuthAuthorityPlane(opts) {
746
747
  },
747
748
  }),
748
749
  issue: async ({ actors, request: r }) => {
749
- const credential = async (key, profile, actor, opts) => mintPublicUserJwt({ space, account: { pub: dataAccount.pub, signingSeed: dataAccount.signingSeed } }, r.identities[key].id, profile, { ...opts, principal: { owner, actor }, lifecycleUid: r.managerLifecycleUid });
750
+ const signer = { space, account: dataAccount };
751
+ const credential = async (key, profile, actor, opts) => mintPublicUserJwt(signer, r.identities[key].id, profile, { ...opts, principal: { owner, actor }, lifecycleUid: r.managerLifecycleUid });
750
752
  const credentials = {};
751
753
  const siblingOn = (gate, observed) => async (key, profile, actor) => {
752
754
  const issued = await credential(key, profile, actor, profile === "goal-writer" ? { goalWriter: { endpoint: "manager" }, expiresInSeconds: standingTtl } : { expiresInSeconds: standingTtl });
@@ -767,7 +769,7 @@ export async function openAuthAuthorityPlane(opts) {
767
769
  return issued;
768
770
  };
769
771
  if (r.operation === "renew") {
770
- const gate = serveIssuanceGateKv(await new Kvm(remoteIssuer.nc).open(epAuthBucket(space)), space, { endpoint: "manager", instanceId: r.instanceId });
772
+ const gate = managerIssuanceGate(r.instanceId);
771
773
  const observed = await gate.observe();
772
774
  if (!observed || observed.state !== "open")
773
775
  throw new EpEnvelopeError("failed-precondition", "manager-service renewal found no current open manager gate");
@@ -798,7 +800,7 @@ export async function openAuthAuthorityPlane(opts) {
798
800
  throw new EpEnvelopeError("permission-denied", "manager-service session proof does not match this owner/lifecycle");
799
801
  const session = r.session;
800
802
  const exp = Math.min(session.exp, Math.floor(Date.now() / 1000) + 24 * 60 * 60);
801
- credentials.sessionServing = await mintPublicUserJwt({ space, account: { pub: dataAccount.pub, signingSeed: dataAccount.signingSeed } }, session.id, "session-serving", {
803
+ credentials.sessionServing = await mintPublicUserJwt(signer, session.id, "session-serving", {
802
804
  principal: { owner, actor: actors.serve },
803
805
  lifecycleUid: r.managerLifecycleUid,
804
806
  sessionServing: { endpoint: "manager", sessionId: session.sessionId, epoch: session.epoch },
@@ -810,7 +812,7 @@ export async function openAuthAuthorityPlane(opts) {
810
812
  const expectedProof = remoteManagerRegistrationProof(owner, r);
811
813
  if (r.registrationProof !== expectedProof)
812
814
  throw new EpEnvelopeError("permission-denied", "manager-service transfer reader proof does not match this owner/lifecycle");
813
- credentials.transferReader = await mintPublicUserJwt({ space, account: { pub: dataAccount.pub, signingSeed: dataAccount.signingSeed } }, r.transferReader.id, "transfer-reader", { principal: { owner, actor: actors.serve }, lifecycleUid: r.managerLifecycleUid, transferReader: { instanceId: r.instanceId } });
815
+ credentials.transferReader = await mintPublicUserJwt(signer, r.transferReader.id, "transfer-reader", { principal: { owner, actor: actors.serve }, lifecycleUid: r.managerLifecycleUid, transferReader: { instanceId: r.instanceId } });
814
816
  return { credentials };
815
817
  }
816
818
  if (r.operation === "retire") {
@@ -818,13 +820,13 @@ export async function openAuthAuthorityPlane(opts) {
818
820
  if (r.registrationProof !== expectedProof)
819
821
  throw new EpEnvelopeError("permission-denied", "manager-service retirement proof does not match this owner/lifecycle");
820
822
  const retirement = r.retirement;
821
- const gate = serveIssuanceGateKv(await new Kvm(remoteIssuer.nc).open(epAuthBucket(space)), space, { endpoint: "manager", instanceId: r.instanceId });
823
+ const gate = managerIssuanceGate(r.instanceId);
822
824
  const observed = await gate.observe();
823
825
  authorizeRemoteManagerRetirement({
824
826
  owner, serveActor: actors.serve, instanceId: r.instanceId,
825
827
  targetOwner: retirement.target.owner, serveEpoch: retirement.serveEpoch, gate: observed,
826
828
  });
827
- credentials.retirementRequester = await mintPublicUserJwt({ space, account: { pub: dataAccount.pub, signingSeed: dataAccount.signingSeed } }, retirement.id, "retirement-requester", {
829
+ credentials.retirementRequester = await mintPublicUserJwt(signer, retirement.id, "retirement-requester", {
828
830
  principal: { owner, actor: actors.serve },
829
831
  lifecycleUid: r.managerLifecycleUid,
830
832
  retirementRequester: {
@@ -839,7 +841,7 @@ export async function openAuthAuthorityPlane(opts) {
839
841
  if (r.operation === "renewStandingBundle") {
840
842
  // authorizeRenewal fresh-checked account, owner, epoch and the current-registration proof
841
843
  // (which binds the held nkeys and lifecycle). Re-observe so every row binds one revision.
842
- const gate = serveIssuanceGateKv(await new Kvm(remoteIssuer.nc).open(epAuthBucket(space)), space, { endpoint: "manager", instanceId: r.instanceId });
844
+ const gate = managerIssuanceGate(r.instanceId);
843
845
  const observed = await gate.observe();
844
846
  if (!observed || observed.state !== "open" || observed.processEpoch !== r.processEpoch)
845
847
  throw new EpEnvelopeError("conflict", "manager-service standing renewal gate moved before issuance");
@@ -851,7 +853,7 @@ export async function openAuthAuthorityPlane(opts) {
851
853
  remoteManager: { instanceId: r.instanceId, owner, actor: actors.executor },
852
854
  expiresInSeconds: 5 * 60,
853
855
  });
854
- credentials.serve = await mintPublicUserJwt({ space, account: { pub: dataAccount.pub, signingSeed: dataAccount.signingSeed } }, r.identities.serve.id, "endpoint-serve", {
856
+ credentials.serve = await mintPublicUserJwt(signer, r.identities.serve.id, "endpoint-serve", {
855
857
  principal: { owner, actor: actors.serve },
856
858
  lifecycleUid: r.managerLifecycleUid,
857
859
  expiresInSeconds: standingTtl,
@@ -864,7 +866,7 @@ export async function openAuthAuthorityPlane(opts) {
864
866
  return { credentials };
865
867
  }
866
868
  if (r.operation === "renewRunDriver") {
867
- const gate = serveIssuanceGateKv(await new Kvm(remoteIssuer.nc).open(epAuthBucket(space)), space, { endpoint: "manager", instanceId: r.instanceId });
869
+ const gate = managerIssuanceGate(r.instanceId);
868
870
  const observed = await gate.observe();
869
871
  if (!observed || observed.state !== "open" || observed.processEpoch !== r.processEpoch)
870
872
  throw new EpEnvelopeError("conflict", "manager-service run renewal gate moved before issuance");
@@ -886,14 +888,13 @@ export async function openAuthAuthorityPlane(opts) {
886
888
  epoch: r.run.epoch,
887
889
  owner,
888
890
  };
889
- const auth = { space, account: { pub: dataAccount.pub, signingSeed: dataAccount.signingSeed } };
890
- credentials.runDriver = await mintPublicUserJwt(auth, r.run.driverId, "run-driver", {
891
+ credentials.runDriver = await mintPublicUserJwt(signer, r.run.driverId, "run-driver", {
891
892
  principal: { owner, actor: caller.actor },
892
893
  lifecycleUid: r.managerLifecycleUid,
893
894
  runDriver: binding,
894
895
  expiresInSeconds: standingTtl,
895
896
  });
896
- credentials.runMediator = await mintPublicUserJwt(auth, r.run.mediatorId, "run-mediator", {
897
+ credentials.runMediator = await mintPublicUserJwt(signer, r.run.mediatorId, "run-mediator", {
897
898
  principal: { owner, actor: caller.actor },
898
899
  lifecycleUid: r.managerLifecycleUid,
899
900
  // Renewed with the placement the attempt was issued with (authorizeRemoteRunAttempt).
@@ -911,19 +912,17 @@ export async function openAuthAuthorityPlane(opts) {
911
912
  // cross HTTP, so the host independently validates the deterministic proof + canonical
912
913
  // artifact set and scopes the JWT to the already-registered instance rails. The grant
913
914
  // rows are reconstructed from the canonical manager command set by the host protocol.
914
- const gate = serveIssuanceGateKv(await new Kvm(remoteIssuer.nc).open(epAuthBucket(space)), space, { endpoint: "manager", instanceId: r.instanceId });
915
+ const gate = managerIssuanceGate(r.instanceId);
915
916
  const observed = await gate.observe();
916
917
  if (!observed)
917
918
  throw new EpEnvelopeError("failed-precondition", "manager-service activation found no issuance gate");
918
- credentials.serve = await mintPublicUserJwt({ space, account: { pub: dataAccount.pub, signingSeed: dataAccount.signingSeed } }, r.identities.serve.id, "endpoint-serve", {
919
+ credentials.serve = await mintPublicUserJwt(signer, r.identities.serve.id, "endpoint-serve", {
919
920
  principal: { owner, actor: actors.serve },
920
921
  lifecycleUid: r.managerLifecycleUid,
921
922
  expiresInSeconds: standingTtl,
922
- endpointServe: reconstructRemoteManagerServeGrant(r, owner, actors.serve, observed),
923
+ endpointServe: reconstructRemoteManagerServeGrant(r, owner, observed),
923
924
  serveIssuance: gate,
924
925
  });
925
- if (!observed)
926
- throw new EpEnvelopeError("failed-precondition", "manager-service activation found no issuance gate");
927
926
  const sibling = siblingOn(gate, observed);
928
927
  credentials.goalWriter = await sibling("goalWriter", "goal-writer", actors.goalWriter);
929
928
  credentials.sessionLedger = await sibling("sessionLedger", "session-ledger", actors.sessionLedger);
@@ -942,12 +941,11 @@ export async function openAuthAuthorityPlane(opts) {
942
941
  maintainRemoteManager: async (holder) => {
943
942
  refuseIfFenced();
944
943
  const { owner } = holder;
945
- const gateKv = await new Kvm(remoteIssuer.nc).open(epAuthBucket(space));
946
944
  const authorized = await authorizeRemoteManagerMaintenance({
947
945
  ...holder,
948
946
  space,
949
947
  scanner,
950
- observeManagerGate: async (instanceId) => serveIssuanceGateKv(gateKv, space, { endpoint: "manager", instanceId }).observe(),
948
+ observeManagerGate,
951
949
  });
952
950
  const evict = makeDeliveryAdminEvictor({ space, server, dataAccount, log });
953
951
  if (authorized.operation === "evict-family-principal") {
@@ -999,10 +997,7 @@ export async function openAuthAuthorityPlane(opts) {
999
997
  ...holder,
1000
998
  proofSecret: dataAccount.signingSeed,
1001
999
  space,
1002
- observeManagerGate: async (instanceId) => {
1003
- const gate = serveIssuanceGateKv(await new Kvm(remoteIssuer.nc).open(epAuthBucket(space)), space, { endpoint: "manager", instanceId });
1004
- return gate.observe();
1005
- },
1000
+ observeManagerGate,
1006
1001
  });
1007
1002
  },
1008
1003
  verifyManagedAgentEnrollment: async ({ owner, scope, request }) => {
@@ -1013,10 +1008,7 @@ export async function openAuthAuthorityPlane(opts) {
1013
1008
  proofSecret: dataAccount.signingSeed,
1014
1009
  space,
1015
1010
  request,
1016
- observeManagerGate: async (instanceId) => {
1017
- const gate = serveIssuanceGateKv(await new Kvm(remoteIssuer.nc).open(epAuthBucket(space)), space, { endpoint: "manager", instanceId });
1018
- return gate.observe();
1019
- },
1011
+ observeManagerGate,
1020
1012
  });
1021
1013
  },
1022
1014
  verifyManagedAgentPrepareRetirement: async ({ owner, scope, request }) => {
@@ -1027,10 +1019,7 @@ export async function openAuthAuthorityPlane(opts) {
1027
1019
  proofSecret: dataAccount.signingSeed,
1028
1020
  space,
1029
1021
  request,
1030
- observeManagerGate: async (instanceId) => {
1031
- const gate = serveIssuanceGateKv(await new Kvm(remoteIssuer.nc).open(epAuthBucket(space)), space, { endpoint: "manager", instanceId });
1032
- return gate.observe();
1033
- },
1022
+ observeManagerGate,
1034
1023
  });
1035
1024
  },
1036
1025
  enrollManagedAgent: async ({ owner, scope, request, sentinelCreds, agentBearerExchangeUrl }) => {
@@ -1155,10 +1144,7 @@ export async function openAuthAuthorityPlane(opts) {
1155
1144
  dir: opts.dir,
1156
1145
  proofSecret: dataAccount.signingSeed,
1157
1146
  space,
1158
- observeManagerGate: async (instanceId) => {
1159
- const gate = serveIssuanceGateKv(await new Kvm(remoteIssuer.nc).open(epAuthBucket(space)), space, { endpoint: "manager", instanceId });
1160
- return gate.observe();
1161
- },
1147
+ observeManagerGate,
1162
1148
  };
1163
1149
  return request.kind === "manager-managed-agent-runtime-status"
1164
1150
  ? authorizeRemoteManagedAgentRuntimeStatus({ ...args, request })
@@ -1169,10 +1155,7 @@ export async function openAuthAuthorityPlane(opts) {
1169
1155
  const { owner } = holder;
1170
1156
  const authorized = await authorizeRemoteManagerGoalIndexScan({
1171
1157
  ...holder, proofSecret: dataAccount.signingSeed, space,
1172
- observeManagerGate: async (instanceId) => {
1173
- const gate = serveIssuanceGateKv(await new Kvm(remoteIssuer.nc).open(epAuthBucket(space)), space, { endpoint: "manager", instanceId });
1174
- return gate.observe();
1175
- },
1158
+ observeManagerGate,
1176
1159
  });
1177
1160
  return completeRemoteManagerGoalIndexScan(authorized, owner, await recordsScanner.scanManagerGoalIndex(owner));
1178
1161
  },
@@ -1185,10 +1168,7 @@ export async function openAuthAuthorityPlane(opts) {
1185
1168
  space,
1186
1169
  dir: opts.dir,
1187
1170
  request,
1188
- observeManagerGate: async (instanceId) => {
1189
- const gate = serveIssuanceGateKv(await new Kvm(remoteIssuer.nc).open(epAuthBucket(space)), space, { endpoint: "manager", instanceId });
1190
- return gate.observe();
1191
- },
1171
+ observeManagerGate,
1192
1172
  });
1193
1173
  },
1194
1174
  admitManagerRun: async ({ request, ...holder }) => {
@@ -1214,10 +1194,7 @@ export async function openAuthAuthorityPlane(opts) {
1214
1194
  try {
1215
1195
  return await admitRemoteRun({
1216
1196
  request, owner, space, accountPublicKey: dataAccount.pub, proofSecret: dataAccount.signingSeed, endpoint: "manager",
1217
- observeManagerGate: async (instanceId) => {
1218
- const gate = serveIssuanceGateKv(await new Kvm(remoteIssuer.nc).open(epAuthBucket(space)), space, { endpoint: "manager", instanceId });
1219
- return gate.observe();
1220
- },
1197
+ observeManagerGate,
1221
1198
  issued: session.store,
1222
1199
  sourceIsLive: composedSourceIsLive(session),
1223
1200
  admissions: await new Kvm(admitterNc).open(admissionBucket(space)),
@@ -1253,12 +1230,28 @@ export async function openAuthAuthorityPlane(opts) {
1253
1230
  accountPublicKey: dataAccount.pub,
1254
1231
  proofSecret: dataAccount.signingSeed,
1255
1232
  endpoint: "manager",
1256
- observeManagerGate: async (instanceId) => {
1257
- const gate = serveIssuanceGateKv(await new Kvm(remoteIssuer.nc).open(epAuthBucket(space)), space, { endpoint: "manager", instanceId });
1258
- return gate.observe();
1259
- },
1233
+ observeManagerGate,
1260
1234
  readAdmission: (runId) => readRunAdmission(recordsJsm, space, "manager", runId),
1261
1235
  readRunStatus: async (runId) => (await readRunRecord(recordsKv, "manager", runId))?.status?.value,
1236
+ // Replayed under a read operator minted for that one run, the rows the manager's own read rides.
1237
+ readJournal: async (runId) => {
1238
+ const takeoverId = newTakeoverId();
1239
+ const readerNc = await connect({
1240
+ servers: server,
1241
+ ...standaloneConnectOpts({
1242
+ creds: await mintCreds(issuerAuth(), newIdentity(), "run-operator", { runOperator: { endpoint: "manager", takeoverId, runId }, expiresInSeconds: 60 }),
1243
+ tls: false,
1244
+ }),
1245
+ maxReconnectAttempts: 0,
1246
+ });
1247
+ try {
1248
+ const replay = await replayRunJournal(jetstream(readerNc), await jetstreamManager(readerNc), space, runId, takeoverId);
1249
+ return replay.records.flatMap((stored) => stored.record.kind === "step" ? [stored.record.entry] : []);
1250
+ }
1251
+ finally {
1252
+ await readerNc.drain().catch(() => readerNc.close());
1253
+ }
1254
+ },
1262
1255
  checkpointWaiting: async (token) => (await readCheckpointStatus(recordsKv, { endpoint: "manager", token }))?.value.state === "waiting",
1263
1256
  checkpointSettled: async (token) => {
1264
1257
  const status = (await readCheckpointStatus(recordsKv, { endpoint: "manager", token }))?.value;
@@ -1331,7 +1324,7 @@ export async function openAuthAuthorityPlane(opts) {
1331
1324
  },
1332
1325
  observeManagerInstance: async (instanceId) => {
1333
1326
  refuseIfFenced();
1334
- const gate = await serveIssuanceGateKv(await new Kvm(remoteIssuer.nc).open(epAuthBucket(space)), space, { endpoint: "manager", instanceId }).observe();
1327
+ const gate = await observeManagerGate(instanceId);
1335
1328
  const rec = await readSvcRecordLeader(recordsJsm, space, recordSpecKey(RECORD_KINDS.svc, ["manager", instanceId]));
1336
1329
  return { registered: rec !== undefined && !("deleted" in rec), gate: gate ?? null };
1337
1330
  },
@@ -1356,7 +1349,7 @@ export async function openAuthAuthorityPlane(opts) {
1356
1349
  },
1357
1350
  observeEndpointGate: async (endpoint, instanceId) => {
1358
1351
  refuseIfFenced();
1359
- return await serveIssuanceGateKv(await new Kvm(remoteIssuer.nc).open(epAuthBucket(space)), space, { endpoint, instanceId }).observe();
1352
+ return await serveIssuanceGateKv(authKv, space, { endpoint, instanceId }).observe();
1360
1353
  },
1361
1354
  fenced,
1362
1355
  close: async () => {