@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/manager-authority.d.ts +9 -3
- package/dist/manager-authority.d.ts.map +1 -1
- package/dist/manager-authority.js +39 -16
- package/dist/manager-authority.js.map +1 -1
- package/dist/manager-contract.d.ts +1 -1
- package/dist/manager-contract.d.ts.map +1 -1
- package/dist/manager-contract.js +2 -4
- package/dist/manager-contract.js.map +1 -1
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +52 -59
- package/dist/service.js.map +1 -1
- package/package.json +4 -3
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
|
|
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
|
|
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
|
|
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 =
|
|
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(
|
|
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(
|
|
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 =
|
|
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(
|
|
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 =
|
|
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(
|
|
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 =
|
|
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
|
-
|
|
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(
|
|
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 =
|
|
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(
|
|
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,
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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(
|
|
1352
|
+
return await serveIssuanceGateKv(authKv, space, { endpoint, instanceId }).observe();
|
|
1360
1353
|
},
|
|
1361
1354
|
fenced,
|
|
1362
1355
|
close: async () => {
|