@cotal-ai/auth 0.78.1 → 0.81.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.
Files changed (42) hide show
  1. package/dist/authority-client.d.ts +11 -0
  2. package/dist/authority-client.d.ts.map +1 -1
  3. package/dist/authority-client.js +22 -0
  4. package/dist/authority-client.js.map +1 -1
  5. package/dist/barrier-evict.d.ts +3 -0
  6. package/dist/barrier-evict.d.ts.map +1 -1
  7. package/dist/barrier-evict.js +1 -1
  8. package/dist/barrier-evict.js.map +1 -1
  9. package/dist/commands.js +6 -4
  10. package/dist/commands.js.map +1 -1
  11. package/dist/delivery-admin.d.ts.map +1 -1
  12. package/dist/delivery-admin.js +2 -9
  13. package/dist/delivery-admin.js.map +1 -1
  14. package/dist/environment-manager-admission-index.d.ts +29 -0
  15. package/dist/environment-manager-admission-index.d.ts.map +1 -0
  16. package/dist/environment-manager-admission-index.js +100 -0
  17. package/dist/environment-manager-admission-index.js.map +1 -0
  18. package/dist/environment-manager-admission.d.ts +15 -0
  19. package/dist/environment-manager-admission.d.ts.map +1 -0
  20. package/dist/environment-manager-admission.js +100 -0
  21. package/dist/environment-manager-admission.js.map +1 -0
  22. package/dist/environment-manager-bootstrap-mint.d.ts +24 -0
  23. package/dist/environment-manager-bootstrap-mint.d.ts.map +1 -0
  24. package/dist/environment-manager-bootstrap-mint.js +92 -0
  25. package/dist/environment-manager-bootstrap-mint.js.map +1 -0
  26. package/dist/ledger-scanner.d.ts.map +1 -1
  27. package/dist/ledger-scanner.js +2 -7
  28. package/dist/ledger-scanner.js.map +1 -1
  29. package/dist/manager-authority.d.ts.map +1 -1
  30. package/dist/manager-authority.js +44 -48
  31. package/dist/manager-authority.js.map +1 -1
  32. package/dist/records-scanner.d.ts.map +1 -1
  33. package/dist/records-scanner.js +2 -6
  34. package/dist/records-scanner.js.map +1 -1
  35. package/dist/service.d.ts.map +1 -1
  36. package/dist/service.js +49 -35
  37. package/dist/service.js.map +1 -1
  38. package/dist/store.d.ts +4 -1
  39. package/dist/store.d.ts.map +1 -1
  40. package/dist/store.js +10 -0
  41. package/dist/store.js.map +1 -1
  42. package/package.json +4 -4
package/dist/service.js CHANGED
@@ -98,7 +98,7 @@ import { joinOrStartRetirement, openAuthAdminListener } from "./auth-admin.js";
98
98
  import { AUTH_SERVICE_ENDPOINT, authClusterArtifacts, authContractArtifactValues } from "./auth-service-contract.js";
99
99
  import { drainTargetForEndpoint, openAdmissionMediator } from "./admission-mediator.js";
100
100
  import { AGENT_BEARER_TTL_SEC, assertWithinSpawnerGrant, findInteractiveActor, findManagedActor, findActorUnified, grantManagedActor, ledgerAclResolver, ledgerActorSourceIsLive, ledgerAuthorizeAgentExchange, ledgerAuthorizeConnect, ledgerAuthorizeGrant, revokeManagedActorAt, } from "./ledger.js";
101
- import { AUTH_PROVIDER_NAME, claimAuthInstanceIdentity, clearAuthServiceInfo, loadCalloutAuth, loadIssuer, loadOwnerSecret, loadPinnedIdp, loadServiceKeys, saveAuthServiceInfo, spaceIssuer, } from "./store.js";
101
+ import { AUTH_PROVIDER_NAME, claimAuthInstanceIdentity, clearAuthServiceInfo, dataAccountAuth, loadCalloutAuth, loadIssuer, loadOwnerSecret, loadPinnedIdp, loadServiceKeys, saveAuthServiceInfo, spaceIssuer, } from "./store.js";
102
102
  /** JWKS max-age seconds — the cache contract's knob. Exported so a rotation tool can compute the
103
103
  * retire floor (max-age + max bearer TTL) from it. */
104
104
  export const JWKS_MAX_AGE_SEC = 300;
@@ -418,6 +418,12 @@ async function buildAuthAuthorityPlane(opts, unwind, onConnection) {
418
418
  const authKv = await new Kvm(remoteIssuer.nc).open(epAuthBucket(space));
419
419
  const managerIssuanceGate = (instanceId) => serveIssuanceGateKv(authKv, space, { endpoint: "manager", instanceId });
420
420
  const observeManagerGate = async (instanceId) => managerIssuanceGate(instanceId).observe();
421
+ const observeLegacyManagerGate = async (instanceId) => {
422
+ const gate = await observeManagerGate(instanceId);
423
+ if (gate?.authorityFamily === "environment-manager")
424
+ throw new EpEnvelopeError("permission-denied", `manager instance ${instanceId} belongs to the environment-manager authority family`);
425
+ return gate;
426
+ };
421
427
  const loadLocalManager = opts.localManager ?? (() => undefined);
422
428
  // Standing renewal and a served resume or answer read the manager surface from the REGISTERED
423
429
  // service spec at the gate's registration revision: spec (leader read) -> closure manifest -> root
@@ -447,7 +453,7 @@ async function buildAuthAuthorityPlane(opts, unwind, onConnection) {
447
453
  };
448
454
  const managerGate = async (owner, instanceId) => {
449
455
  const localManager = loadLocalManager();
450
- const gate = await observeManagerGate(instanceId);
456
+ const gate = await observeLegacyManagerGate(instanceId);
451
457
  if (!gate)
452
458
  return "unknown";
453
459
  if (gate.state !== "open")
@@ -492,6 +498,8 @@ async function buildAuthAuthorityPlane(opts, unwind, onConnection) {
492
498
  throw new EpEnvelopeError("internal", `the manager gate scan returned the malformed key ${raw.key}`);
493
499
  const instanceId = assertLifecycleToken(parts[2], "managerInstanceId");
494
500
  const row = parseEndpointGate(raw.data, raw.key);
501
+ if (row.authorityFamily === "environment-manager")
502
+ continue;
495
503
  if (row.principal === `${owner}.${remoteManagerActors(instanceId).serve}`) {
496
504
  remoteInstances.push(instanceId);
497
505
  if (await managerGate(owner, instanceId) === "candidate")
@@ -521,14 +529,7 @@ async function buildAuthAuthorityPlane(opts, unwind, onConnection) {
521
529
  if (fatalReason !== undefined || closing)
522
530
  throw new EpEnvelopeError("unavailable", `the auth service for space "${space}" is momentarily unavailable (it detected a fault and is restarting); retry shortly`);
523
531
  };
524
- // The plane holds only the data account's signing key. The operator and system halves stay blank
525
- // because core's mint reads only the space, the account pub and the signing seed.
526
- const issuerAuth = () => ({
527
- space,
528
- operator: { seed: "", jwt: "" },
529
- account: { pub: dataAccount.pub, seed: "", jwt: "", signingSeed: dataAccount.signingSeed, signingPub: "" },
530
- sys: { pub: "", jwt: "" },
531
- });
532
+ const issuerAuth = () => dataAccountAuth(space, dataAccount);
532
533
  // The source check the issuing host resolves with: an actor-ledger row is attested here, from the
533
534
  // ledger this service owns; every other coordinate goes to core's check (SPEC 13.15).
534
535
  const composedSourceIsLive = (session) => (source) => parseActorLedgerSource(source) ? Promise.resolve(ledgerActorSourceIsLive(opts.dir)(source)) : session.sourceIsLive(source);
@@ -628,7 +629,7 @@ async function buildAuthAuthorityPlane(opts, unwind, onConnection) {
628
629
  space,
629
630
  managerGate: async (owner, instanceId) => {
630
631
  const verdict = await managerGate(owner, assertLifecycleToken(instanceId, "serving.instanceId"));
631
- const gate = await observeManagerGate(instanceId);
632
+ const gate = await observeLegacyManagerGate(instanceId);
632
633
  return { verdict, ...(gate ? { processEpoch: gate.processEpoch } : {}) };
633
634
  },
634
635
  }, principal, claim);
@@ -706,7 +707,7 @@ async function buildAuthAuthorityPlane(opts, unwind, onConnection) {
706
707
  // The ended-assignment fence (SPEC 13.16): read on every call, before anything is signed. The
707
708
  // retired gate and the retired generations are terminal rows, so no host view reopens them.
708
709
  if (holder.supervisorExpiresAt !== undefined) {
709
- const gate = await observeManagerGate(holder.request.instanceId);
710
+ const gate = await observeLegacyManagerGate(holder.request.instanceId);
710
711
  if (gate?.state === "retired")
711
712
  throw platformSupervisorEnded(owner);
712
713
  await withIssuerSession({ servers: server, space, auth: issuerAuth(), tls: false }, async (session) => {
@@ -728,11 +729,16 @@ async function buildAuthAuthorityPlane(opts, unwind, onConnection) {
728
729
  ...holder,
729
730
  authorizeRenewal: ({ owner: o, request: r }) => authorizeRemoteManagerRenewal({
730
731
  request: r, owner: o, space, accountPublicKey: dataAccount.pub, proofSecret: dataAccount.signingSeed,
731
- observeManagerGate,
732
+ observeManagerGate: observeLegacyManagerGate,
732
733
  observeRun: (runId) => observeManagerRun(r, runId),
733
734
  }),
734
735
  issue: async ({ actors, request: r }) => {
735
- const signer = { space, account: dataAccount };
736
+ const existing = await observeLegacyManagerGate(r.instanceId);
737
+ if (r.operation === "prepare" && existing === null) {
738
+ await provisionEndpointGateOpen(authKv, {
739
+ endpoint: "manager", instanceId: r.instanceId, principal: `${owner}.${actors.serve}`,
740
+ });
741
+ }
736
742
  const bounded = (opts) => {
737
743
  if (holder.supervisorExpiresAt === undefined)
738
744
  return opts;
@@ -743,7 +749,7 @@ async function buildAuthAuthorityPlane(opts, unwind, onConnection) {
743
749
  return { ...rest, expiresAt: Math.min(holder.supervisorExpiresAt, expiresAt ?? now + (expiresInSeconds ?? standingTtl)) };
744
750
  };
745
751
  const registration = { space: r.space, instanceId: r.instanceId, lifecycleUid: r.managerLifecycleUid, identities: r.identities };
746
- const credential = async (key, profile, actor, opts) => mintPublicUserJwt(signer, r.identities[key].id, profile, bounded({ ...opts, principal: { owner, actor }, lifecycleUid: r.managerLifecycleUid }));
752
+ const credential = async (key, profile, actor, opts) => mintPublicUserJwt(issuerAuth(), r.identities[key].id, profile, bounded({ ...opts, principal: { owner, actor }, lifecycleUid: r.managerLifecycleUid }));
747
753
  const credentials = {};
748
754
  const siblingOn = (gate, observed) => async (key, profile, actor) => {
749
755
  const issued = await credential(key, profile, actor, profile === "goal-writer" ? { goalWriter: { endpoint: "manager" }, expiresInSeconds: standingTtl } : { expiresInSeconds: standingTtl });
@@ -794,7 +800,7 @@ async function buildAuthAuthorityPlane(opts, unwind, onConnection) {
794
800
  throw new EpEnvelopeError("permission-denied", "manager-service session proof does not match this owner/lifecycle");
795
801
  const session = r.session;
796
802
  const exp = Math.min(session.exp, Math.floor(Date.now() / 1000) + 24 * 60 * 60);
797
- credentials.sessionServing = await mintPublicUserJwt(signer, session.id, "session-serving", {
803
+ credentials.sessionServing = await mintPublicUserJwt(issuerAuth(), session.id, "session-serving", {
798
804
  principal: { owner, actor: actors.serve },
799
805
  lifecycleUid: r.managerLifecycleUid,
800
806
  sessionServing: { endpoint: "manager", sessionId: session.sessionId, epoch: session.epoch },
@@ -806,7 +812,7 @@ async function buildAuthAuthorityPlane(opts, unwind, onConnection) {
806
812
  const expectedProof = remoteManagerRegistrationProof(owner, registration);
807
813
  if (r.registrationProof !== expectedProof)
808
814
  throw new EpEnvelopeError("permission-denied", "manager-service transfer reader proof does not match this owner/lifecycle");
809
- credentials.transferReader = await mintPublicUserJwt(signer, r.transferReader.id, "transfer-reader", { principal: { owner, actor: actors.serve }, lifecycleUid: r.managerLifecycleUid, transferReader: { instanceId: r.instanceId } });
815
+ credentials.transferReader = await mintPublicUserJwt(issuerAuth(), r.transferReader.id, "transfer-reader", { principal: { owner, actor: actors.serve }, lifecycleUid: r.managerLifecycleUid, transferReader: { instanceId: r.instanceId } });
810
816
  return { credentials };
811
817
  }
812
818
  if (r.operation === "retire") {
@@ -820,7 +826,7 @@ async function buildAuthAuthorityPlane(opts, unwind, onConnection) {
820
826
  owner, serveActor: actors.serve, instanceId: r.instanceId,
821
827
  targetOwner: retirement.target.owner, serveEpoch: retirement.serveEpoch, gate: observed,
822
828
  });
823
- credentials.retirementRequester = await mintPublicUserJwt(signer, retirement.id, "retirement-requester", {
829
+ credentials.retirementRequester = await mintPublicUserJwt(issuerAuth(), retirement.id, "retirement-requester", {
824
830
  principal: { owner, actor: actors.serve },
825
831
  lifecycleUid: r.managerLifecycleUid,
826
832
  retirementRequester: {
@@ -847,7 +853,7 @@ async function buildAuthAuthorityPlane(opts, unwind, onConnection) {
847
853
  remoteManager: { instanceId: r.instanceId, owner, actor: actors.executor },
848
854
  expiresInSeconds: 5 * 60,
849
855
  });
850
- credentials.serve = await mintPublicUserJwt(signer, r.identities.serve.id, "endpoint-serve", bounded({
856
+ credentials.serve = await mintPublicUserJwt(issuerAuth(), r.identities.serve.id, "endpoint-serve", bounded({
851
857
  principal: { owner, actor: actors.serve },
852
858
  lifecycleUid: r.managerLifecycleUid,
853
859
  expiresInSeconds: standingTtl,
@@ -875,13 +881,13 @@ async function buildAuthAuthorityPlane(opts, unwind, onConnection) {
875
881
  epoch: r.run.epoch,
876
882
  owner,
877
883
  };
878
- credentials.runDriver = await mintPublicUserJwt(signer, r.run.driverId, "run-driver", bounded({
884
+ credentials.runDriver = await mintPublicUserJwt(issuerAuth(), r.run.driverId, "run-driver", bounded({
879
885
  principal: { owner, actor: caller.actor },
880
886
  lifecycleUid: r.managerLifecycleUid,
881
887
  runDriver: binding,
882
888
  expiresInSeconds: standingTtl,
883
889
  }));
884
- credentials.runMediator = await mintPublicUserJwt(signer, r.run.mediatorId, "run-mediator", bounded({
890
+ credentials.runMediator = await mintPublicUserJwt(issuerAuth(), r.run.mediatorId, "run-mediator", bounded({
885
891
  principal: { owner, actor: caller.actor },
886
892
  lifecycleUid: r.managerLifecycleUid,
887
893
  // Renewed with the placement the attempt was issued with (authorizeRemoteRunAttempt).
@@ -903,7 +909,7 @@ async function buildAuthAuthorityPlane(opts, unwind, onConnection) {
903
909
  const observed = await gate.observe();
904
910
  if (!observed)
905
911
  throw new EpEnvelopeError("failed-precondition", "manager-service activation found no issuance gate");
906
- credentials.serve = await mintPublicUserJwt(signer, r.identities.serve.id, "endpoint-serve", bounded({
912
+ credentials.serve = await mintPublicUserJwt(issuerAuth(), r.identities.serve.id, "endpoint-serve", bounded({
907
913
  principal: { owner, actor: actors.serve },
908
914
  lifecycleUid: r.managerLifecycleUid,
909
915
  expiresInSeconds: standingTtl,
@@ -954,6 +960,7 @@ async function buildAuthAuthorityPlane(opts, unwind, onConnection) {
954
960
  },
955
961
  endPlatformSupervisor: async ({ owner, instanceId, lifecycleUid }) => {
956
962
  refuseIfFenced();
963
+ await observeLegacyManagerGate(instanceId);
957
964
  // Retire the issued generations first, then the gate. Each step is idempotent, so a retry after
958
965
  // a partial end completes it. The retired gate alone refuses a lifecycle that issued nothing.
959
966
  await withIssuerSession({ servers: server, space, auth: issuerAuth(), tls: false }, async (session) => {
@@ -984,6 +991,8 @@ async function buildAuthAuthorityPlane(opts, unwind, onConnection) {
984
991
  if (entry.operation !== "PUT")
985
992
  throw new EpEnvelopeError("failed-precondition", `the manager gate ${key} carries a ${entry.operation} marker; a gate is never deleted (SPEC 13.12)`);
986
993
  const row = parseEndpointGate(entry.value, key);
994
+ if (row.authorityFamily === "environment-manager")
995
+ throw new EpEnvelopeError("permission-denied", `manager instance ${instanceId} belongs to the environment-manager authority family`);
987
996
  if (row.principal !== `${owner}.${remoteManagerActors(instanceId).serve}`)
988
997
  throw new EpEnvelopeError("permission-denied", `the manager gate ${key} belongs to ${row.principal}, not owner ${owner}`);
989
998
  if (row.state === "retired")
@@ -1004,11 +1013,12 @@ async function buildAuthAuthorityPlane(opts, unwind, onConnection) {
1004
1013
  maintainRemoteManager: async (holder) => {
1005
1014
  refuseIfFenced();
1006
1015
  const { owner } = holder;
1016
+ await observeLegacyManagerGate(holder.request.instanceId);
1007
1017
  const authorized = await authorizeRemoteManagerMaintenance({
1008
1018
  ...holder,
1009
1019
  space,
1010
1020
  scanner,
1011
- observeManagerGate,
1021
+ observeManagerGate: observeLegacyManagerGate,
1012
1022
  });
1013
1023
  const evictHolders = makeDeliveryAdminHolderEvictor({ onConnection, space, server, dataAccount, log });
1014
1024
  if (authorized.operation === "evict-family-principal") {
@@ -1055,7 +1065,7 @@ async function buildAuthAuthorityPlane(opts, unwind, onConnection) {
1055
1065
  ...holder,
1056
1066
  proofSecret: dataAccount.signingSeed,
1057
1067
  space,
1058
- observeManagerGate,
1068
+ observeManagerGate: observeLegacyManagerGate,
1059
1069
  });
1060
1070
  },
1061
1071
  verifyManagedAgentEnrollment: async ({ owner, scope, request }) => {
@@ -1066,7 +1076,7 @@ async function buildAuthAuthorityPlane(opts, unwind, onConnection) {
1066
1076
  proofSecret: dataAccount.signingSeed,
1067
1077
  space,
1068
1078
  request,
1069
- observeManagerGate,
1079
+ observeManagerGate: observeLegacyManagerGate,
1070
1080
  });
1071
1081
  },
1072
1082
  verifyManagedAgentPrepareRetirement: async ({ owner, scope, request }) => {
@@ -1077,12 +1087,12 @@ async function buildAuthAuthorityPlane(opts, unwind, onConnection) {
1077
1087
  proofSecret: dataAccount.signingSeed,
1078
1088
  space,
1079
1089
  request,
1080
- observeManagerGate,
1090
+ observeManagerGate: observeLegacyManagerGate,
1081
1091
  });
1082
1092
  },
1083
1093
  enrollManagedAgent: async ({ owner, scope, request, sentinelCreds, agentBearerExchangeUrl }) => {
1084
1094
  refuseIfFenced();
1085
- const r = await authorizeRemoteManagedAgentEnrollment({ owner, scope, proofSecret: dataAccount.signingSeed, space, request, observeManagerGate });
1095
+ const r = await authorizeRemoteManagedAgentEnrollment({ owner, scope, proofSecret: dataAccount.signingSeed, space, request, observeManagerGate: observeLegacyManagerGate });
1086
1096
  const t = r.target;
1087
1097
  const subscribe = t.subscribe ?? [];
1088
1098
  const { lifecycleUid, row } = await serializedForAlias(opts.dir, owner, t.actor, async () => {
@@ -1170,7 +1180,7 @@ async function buildAuthAuthorityPlane(opts, unwind, onConnection) {
1170
1180
  },
1171
1181
  prepareManagedAgentRetirement: async ({ owner, scope, request }) => {
1172
1182
  refuseIfFenced();
1173
- const r = await authorizeRemoteManagedAgentPrepareRetirement({ owner, scope, proofSecret: dataAccount.signingSeed, space, request, observeManagerGate });
1183
+ const r = await authorizeRemoteManagedAgentPrepareRetirement({ owner, scope, proofSecret: dataAccount.signingSeed, space, request, observeManagerGate: observeLegacyManagerGate });
1174
1184
  const { actor, lifecycleUid } = r.target;
1175
1185
  await serializedForAlias(opts.dir, owner, actor, async () => {
1176
1186
  // Only a grant still at the target uid is this lifecycle's. A row at another uid belongs to a
@@ -1203,7 +1213,7 @@ async function buildAuthAuthorityPlane(opts, unwind, onConnection) {
1203
1213
  dir: opts.dir,
1204
1214
  proofSecret: dataAccount.signingSeed,
1205
1215
  space,
1206
- observeManagerGate,
1216
+ observeManagerGate: observeLegacyManagerGate,
1207
1217
  };
1208
1218
  return request.kind === "manager-managed-agent-runtime-status"
1209
1219
  ? authorizeRemoteManagedAgentRuntimeStatus({ ...args, request })
@@ -1214,7 +1224,7 @@ async function buildAuthAuthorityPlane(opts, unwind, onConnection) {
1214
1224
  const { owner } = holder;
1215
1225
  const authorized = await authorizeRemoteManagerGoalIndexScan({
1216
1226
  ...holder, proofSecret: dataAccount.signingSeed, space,
1217
- observeManagerGate,
1227
+ observeManagerGate: observeLegacyManagerGate,
1218
1228
  });
1219
1229
  return completeRemoteManagerGoalIndexScan(authorized, owner, await recordsScanner.scanManagerGoalIndex(owner));
1220
1230
  },
@@ -1227,14 +1237,16 @@ async function buildAuthAuthorityPlane(opts, unwind, onConnection) {
1227
1237
  space,
1228
1238
  dir: opts.dir,
1229
1239
  request,
1230
- observeManagerGate,
1240
+ observeManagerGate: observeLegacyManagerGate,
1231
1241
  });
1232
1242
  },
1233
1243
  admitManagerRun: async ({ request, ...holder }) => {
1234
1244
  refuseIfFenced();
1235
1245
  const { owner } = holder;
1236
1246
  requireManagerAuthorityHolder(holder, String(request?.instanceId), 'manager run admission needs scope "supervise"; spawn/admin do not imply it');
1237
- const runId = parseRemoteRunAdmissionRequest(request).run.runId;
1247
+ const parsed = parseRemoteRunAdmissionRequest(request);
1248
+ await observeLegacyManagerGate(parsed.instanceId);
1249
+ const runId = parsed.run.runId;
1238
1250
  return withIssuerSession({ servers: server, space, auth: issuerAuth(), tls: false }, async (session) => {
1239
1251
  const admitterNc = await connect({
1240
1252
  servers: server,
@@ -1248,7 +1260,7 @@ async function buildAuthAuthorityPlane(opts, unwind, onConnection) {
1248
1260
  try {
1249
1261
  return await admitRemoteRun({
1250
1262
  request, owner, space, accountPublicKey: dataAccount.pub, proofSecret: dataAccount.signingSeed, endpoint: "manager",
1251
- observeManagerGate,
1263
+ observeManagerGate: observeLegacyManagerGate,
1252
1264
  issued: session.store,
1253
1265
  sourceIsLive: composedSourceIsLive(session),
1254
1266
  takeObserved: takeObservedRunRequest,
@@ -1263,6 +1275,7 @@ async function buildAuthAuthorityPlane(opts, unwind, onConnection) {
1263
1275
  revokeManagerRun: async ({ request, ...holder }) => {
1264
1276
  refuseIfFenced();
1265
1277
  const req = parseRemoteRunRevokeRequest(request);
1278
+ await observeLegacyManagerGate(req.instanceId);
1266
1279
  const admitterNc = await connect({
1267
1280
  servers: server,
1268
1281
  ...standaloneConnectOpts({
@@ -1275,7 +1288,7 @@ async function buildAuthAuthorityPlane(opts, unwind, onConnection) {
1275
1288
  try {
1276
1289
  return await revokeRemoteRun({
1277
1290
  ...holder, request: req, space, accountPublicKey: dataAccount.pub, proofSecret: dataAccount.signingSeed, endpoint: "manager",
1278
- observeManagerGate,
1291
+ observeManagerGate: observeLegacyManagerGate,
1279
1292
  readAdmission: (runId) => readRunAdmission(recordsJsm, space, "manager", runId),
1280
1293
  readRevocation: (runId) => readRunRevocation(recordsJsm, space, "manager", runId),
1281
1294
  admissions: await new Kvm(admitterNc).open(admissionBucket(space)),
@@ -1290,6 +1303,7 @@ async function buildAuthAuthorityPlane(opts, unwind, onConnection) {
1290
1303
  const { owner } = holder;
1291
1304
  requireManagerAuthorityHolder(holder, String(request?.instanceId), 'manager run attempt needs scope "supervise"; spawn/admin do not imply it');
1292
1305
  const req = parseRemoteRunAttemptRequest(request);
1306
+ await observeLegacyManagerGate(req.instanceId);
1293
1307
  const recordsKv = await openRecordsBucket(remoteIssuer.nc, space);
1294
1308
  const authorize = (session) => authorizeRemoteRunAttempt({
1295
1309
  ...(session ? { issued: session.store, sourceIsLive: composedSourceIsLive(session) } : {}),
@@ -1310,7 +1324,7 @@ async function buildAuthAuthorityPlane(opts, unwind, onConnection) {
1310
1324
  accountPublicKey: dataAccount.pub,
1311
1325
  proofSecret: dataAccount.signingSeed,
1312
1326
  endpoint: "manager",
1313
- observeManagerGate,
1327
+ observeManagerGate: observeLegacyManagerGate,
1314
1328
  readAdmission: (runId) => readRunAdmission(recordsJsm, space, "manager", runId),
1315
1329
  readRunStatus: async (runId) => (await readRunRecord(recordsKv, "manager", runId))?.status?.value,
1316
1330
  // Replayed under a read operator minted for that one run, the rows the manager's own read rides.