@cotal-ai/auth 0.59.0 → 0.61.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/derive.d.ts +5 -0
- package/dist/derive.d.ts.map +1 -1
- package/dist/derive.js +15 -1
- package/dist/derive.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/manager-admin-authorization.d.ts +13 -4
- package/dist/manager-admin-authorization.d.ts.map +1 -1
- package/dist/manager-admin-authorization.js +15 -7
- package/dist/manager-admin-authorization.js.map +1 -1
- package/dist/manager-authority.d.ts +11 -7
- package/dist/manager-authority.d.ts.map +1 -1
- package/dist/manager-authority.js +9 -7
- package/dist/manager-authority.js.map +1 -1
- package/dist/manager-goal-index.d.ts +2 -3
- package/dist/manager-goal-index.d.ts.map +1 -1
- package/dist/manager-goal-index.js +2 -2
- package/dist/manager-goal-index.js.map +1 -1
- package/dist/manager-maintenance.d.ts +2 -3
- package/dist/manager-maintenance.d.ts.map +1 -1
- package/dist/manager-maintenance.js +8 -2
- package/dist/manager-maintenance.js.map +1 -1
- package/dist/platform-control.d.ts +47 -0
- package/dist/platform-control.d.ts.map +1 -0
- package/dist/platform-control.js +117 -0
- package/dist/platform-control.js.map +1 -0
- package/dist/records-scanner.d.ts.map +1 -1
- package/dist/records-scanner.js +3 -2
- package/dist/records-scanner.js.map +1 -1
- package/dist/retained-manager-validation.d.ts +9 -6
- package/dist/retained-manager-validation.d.ts.map +1 -1
- package/dist/retained-manager-validation.js +9 -7
- package/dist/retained-manager-validation.js.map +1 -1
- package/dist/service.d.ts +71 -30
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +97 -42
- package/dist/service.js.map +1 -1
- package/package.json +3 -3
package/dist/service.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type IncomingMessage, type ServerResponse } from "node:http";
|
|
2
|
-
import { type ParsedArgs, type RemoteManagerAdminAuthorizationRequest, type RemoteManagerAuthorityRequest, type RemoteManagerMaintenanceRequest, type RemoteRetainedAgentValidationRequest, type SecretStore } from "@cotal-ai/core";
|
|
2
|
+
import { type EpGateState, type ParsedArgs, type PlatformControlAssignment, type PlatformControlAuthorityRequest, type PlatformControlAuthorityResult, type PlatformControlInnerRequest, type RemoteManagerAdminAuthorizationRequest, type RemoteManagerAuthorityRequest, type RemoteManagerMaintenanceRequest, type RemoteRetainedAgentValidationRequest, type SecretStore } from "@cotal-ai/core";
|
|
3
3
|
import { type HostedContextInputs, type HostedServiceHandle, type ManagerInstanceIdentity } from "@cotal-ai/workspace";
|
|
4
|
+
import { type ManagerAuthorityHolder } from "./platform-control.js";
|
|
4
5
|
import { type IdpBridge } from "./idp.js";
|
|
5
6
|
import { type UserTokenSession, type ValidatedUserToken } from "./token.js";
|
|
6
7
|
import { pinnedJwksResolver, type UserTokenIssuer } from "./issuer.js";
|
|
@@ -55,19 +56,13 @@ export interface AuthAuthorityPlane {
|
|
|
55
56
|
alreadyRetired?: boolean;
|
|
56
57
|
}>;
|
|
57
58
|
retireManagedLifecycle: AuthAuthorityPlane["retireInteractiveLifecycle"];
|
|
58
|
-
issueManagerServiceAuthority: (args: {
|
|
59
|
-
owner: string;
|
|
60
|
-
scope: string[];
|
|
59
|
+
issueManagerServiceAuthority: (args: ManagerAuthorityHolder & {
|
|
61
60
|
request: RemoteManagerAuthorityRequest;
|
|
62
61
|
}) => Promise<import("@cotal-ai/core").RemoteManagerAuthorityMaterial>;
|
|
63
|
-
maintainRemoteManager: (args: {
|
|
64
|
-
owner: string;
|
|
65
|
-
scope: string[];
|
|
62
|
+
maintainRemoteManager: (args: ManagerAuthorityHolder & {
|
|
66
63
|
request: RemoteManagerMaintenanceRequest;
|
|
67
64
|
}) => Promise<import("@cotal-ai/core").RemoteManagerMaintenanceResult>;
|
|
68
|
-
validateRetainedAgent: (args: {
|
|
69
|
-
owner: string;
|
|
70
|
-
scope: string[];
|
|
65
|
+
validateRetainedAgent: (args: ManagerAuthorityHolder & {
|
|
71
66
|
request: RemoteRetainedAgentValidationRequest;
|
|
72
67
|
}) => Promise<RemoteRetainedAgentValidationRequest>;
|
|
73
68
|
/** Authorize one host-owned managed-agent enrollment (#1972). The plane reads the manager gate on
|
|
@@ -90,33 +85,31 @@ export interface AuthAuthorityPlane {
|
|
|
90
85
|
owner: string;
|
|
91
86
|
request: import("@cotal-ai/core").RemoteManagedAgentRuntimeRequest;
|
|
92
87
|
}) => Promise<RemoteManagedAgentRuntimeDecision>;
|
|
93
|
-
scanManagerGoalIndex: (args: {
|
|
94
|
-
owner: string;
|
|
95
|
-
scope: string[];
|
|
88
|
+
scanManagerGoalIndex: (args: ManagerAuthorityHolder & {
|
|
96
89
|
request: import("@cotal-ai/core").RemoteManagerGoalIndexScanRequest;
|
|
97
90
|
}) => Promise<import("@cotal-ai/core").RemoteManagerGoalIndexScanResult>;
|
|
98
|
-
authorizeManagerAdmin: (args: {
|
|
99
|
-
owner: string;
|
|
100
|
-
scope: string[];
|
|
91
|
+
authorizeManagerAdmin: (args: ManagerAuthorityHolder & {
|
|
101
92
|
request: RemoteManagerAdminAuthorizationRequest;
|
|
102
93
|
}) => Promise<import("@cotal-ai/core").RemoteManagerAdminAuthorizationResult>;
|
|
103
94
|
/** First-run admission for one hosted run-start, asked by a registered signerless manager. The
|
|
104
95
|
* plane authenticates the registration, resolves the caller's issued generation on its own issuer
|
|
105
96
|
* connection with live sources, and creates the admission through a run-admitter credential
|
|
106
97
|
* pinned to that one run. No ceiling, caller or profile is taken from the request. */
|
|
107
|
-
admitManagerRun: (args: {
|
|
108
|
-
owner: string;
|
|
109
|
-
scope: string[];
|
|
98
|
+
admitManagerRun: (args: ManagerAuthorityHolder & {
|
|
110
99
|
request: unknown;
|
|
111
100
|
}) => Promise<import("@cotal-ai/core").RemoteRunAdmissionResult>;
|
|
112
101
|
/** First-attempt/resume or operator issuance for one hosted run, asked by a registered signerless manager.
|
|
113
102
|
* The plane authenticates the registration, derives coordinates from native admission/records/checkpoints,
|
|
114
103
|
* and signs ONLY the returned fixed grant args. JWT responses contain no seeds. */
|
|
115
|
-
issueManagerRunAttempt: (args: {
|
|
116
|
-
owner: string;
|
|
117
|
-
scope: string[];
|
|
104
|
+
issueManagerRunAttempt: (args: ManagerAuthorityHolder & {
|
|
118
105
|
request: unknown;
|
|
119
106
|
}) => Promise<import("@cotal-ai/core").RemoteRunAttemptResult>;
|
|
107
|
+
/** Read-only view of one manager instance for the platform control door: whether its
|
|
108
|
+
* `svc.manager` record is current, and its gate. It probes, freezes and writes nothing. */
|
|
109
|
+
observeManagerInstance: (instanceId: string) => Promise<{
|
|
110
|
+
registered: boolean;
|
|
111
|
+
gate: EpGateState | null;
|
|
112
|
+
}>;
|
|
120
113
|
/** Resolves with the state-3 copy when a mid-life scanner death FENCES the plane (SPEC 13.13):
|
|
121
114
|
* the plane is no longer whole, `authorizeConnect`/`mintConnectCredential` refuse from that
|
|
122
115
|
* moment, and the composition root must take the whole service DOWN loud (a fenced plane that
|
|
@@ -197,10 +190,33 @@ export declare function openAuthAuthorityPlane(opts: {
|
|
|
197
190
|
* NON-SEAM state (the actor ledger, the IdP pin, the discovery file) still lives in the local
|
|
198
191
|
* state dir either way — hosting those is a later, separate seam. */
|
|
199
192
|
export declare function runAuthService(args: ParsedArgs, store?: SecretStore): Promise<void>;
|
|
200
|
-
/** An embedded auth-service context:
|
|
193
|
+
/** An embedded auth-service context: what `runAuthService` writes to `auth-service.json` (the
|
|
194
|
+
* loopback URL, the public URL and the capability) plus the hosted lifecycle handle. */
|
|
201
195
|
export interface AuthServiceHandle extends HostedServiceHandle {
|
|
202
196
|
readonly url: string;
|
|
203
197
|
readonly publicUrl?: string;
|
|
198
|
+
/** The per-start loopback capability. It alone authorizes the loopback host actions (lifecycle
|
|
199
|
+
* retirement, managed-agent enrollment verification), so it stays in the authority process and
|
|
200
|
+
* never reaches a control worker. */
|
|
201
|
+
readonly cap: string;
|
|
202
|
+
/** The platform control door (SPEC 13.1). Present only when `platformControl` was supplied to
|
|
203
|
+
* {@link startAuthService}. In-process and typed: no route, no capability, and no signer or
|
|
204
|
+
* capability in the result. */
|
|
205
|
+
platformControlAuthority?<R extends PlatformControlInnerRequest>(request: PlatformControlAuthorityRequest<R>): Promise<PlatformControlAuthorityResult<R>>;
|
|
206
|
+
}
|
|
207
|
+
/** The optional public exchange face: the CLI's `--exchange-public-*`, `--advertised-server` and
|
|
208
|
+
* `--agent-provisioning-url` flags, or the hosted `publicFace` input. */
|
|
209
|
+
export interface PublicFaceInput {
|
|
210
|
+
port: number;
|
|
211
|
+
url?: string;
|
|
212
|
+
trustedProxy: boolean;
|
|
213
|
+
advertisedServer?: string;
|
|
214
|
+
agentProvisioningUrl?: string;
|
|
215
|
+
}
|
|
216
|
+
/** The platform composition's input for the platform control door. */
|
|
217
|
+
export interface PlatformControlInput {
|
|
218
|
+
/** The one current assignment for this account, or null. Read fresh on every door call. */
|
|
219
|
+
observeAssignment(space: string, accountPublicKey: string): Promise<PlatformControlAssignment | null>;
|
|
204
220
|
}
|
|
205
221
|
/** Start one account-scoped auth-service context. Every input is explicit: the state dir, the
|
|
206
222
|
* injected store with its proved identity, the assigned data account and the broker. The context
|
|
@@ -210,7 +226,18 @@ export interface AuthServiceHandle extends HostedServiceHandle {
|
|
|
210
226
|
* mid-life fence or broker loss makes only this context `unavailable` and closes its resources. */
|
|
211
227
|
export declare function startAuthService(inputs: HostedContextInputs & {
|
|
212
228
|
port?: number;
|
|
229
|
+
/** Absent: the handle has no `publicUrl` and nothing serves the discovery bundle. */
|
|
230
|
+
publicFace?: PublicFaceInput;
|
|
231
|
+
/** Present only in a platform composition. Absent: the handle has no platform control door. */
|
|
232
|
+
platformControl?: PlatformControlInput;
|
|
233
|
+
/** Trusted-host only. Forwarded unchanged to {@link openAuthAuthorityPlane}, which bounds it to
|
|
234
|
+
* 5..86400 seconds. Absent: the 24h default. No CLI flag and no request field sets it. */
|
|
235
|
+
standingRenewableTtlSeconds?: number;
|
|
213
236
|
}): Promise<AuthServiceHandle>;
|
|
237
|
+
/** The HTTP routes authenticate a human, so they only ever supply the human arm. */
|
|
238
|
+
type HumanHolder = Extract<ManagerAuthorityHolder, {
|
|
239
|
+
scope: string[];
|
|
240
|
+
}>;
|
|
214
241
|
interface HandlerCtx {
|
|
215
242
|
issuer: UserTokenIssuer;
|
|
216
243
|
bridge: IdpBridge;
|
|
@@ -220,16 +247,30 @@ interface HandlerCtx {
|
|
|
220
247
|
key: ReturnType<typeof pinnedJwksResolver>;
|
|
221
248
|
};
|
|
222
249
|
ownerSecret: string | Uint8Array;
|
|
223
|
-
managerServiceAuthority:
|
|
224
|
-
|
|
225
|
-
|
|
250
|
+
managerServiceAuthority: (args: HumanHolder & {
|
|
251
|
+
request: RemoteManagerAuthorityRequest;
|
|
252
|
+
}) => ReturnType<AuthAuthorityPlane["issueManagerServiceAuthority"]>;
|
|
253
|
+
maintainRemoteManager: (args: HumanHolder & {
|
|
254
|
+
request: RemoteManagerMaintenanceRequest;
|
|
255
|
+
}) => ReturnType<AuthAuthorityPlane["maintainRemoteManager"]>;
|
|
256
|
+
validateRetainedAgent: (args: HumanHolder & {
|
|
257
|
+
request: RemoteRetainedAgentValidationRequest;
|
|
258
|
+
}) => ReturnType<AuthAuthorityPlane["validateRetainedAgent"]>;
|
|
226
259
|
verifyManagedAgentEnrollment: AuthAuthorityPlane["verifyManagedAgentEnrollment"];
|
|
227
260
|
verifyManagedAgentPrepareRetirement: AuthAuthorityPlane["verifyManagedAgentPrepareRetirement"];
|
|
228
261
|
verifyManagedAgentRuntime: AuthAuthorityPlane["verifyManagedAgentRuntime"];
|
|
229
|
-
scanManagerGoalIndex:
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
262
|
+
scanManagerGoalIndex: (args: HumanHolder & {
|
|
263
|
+
request: import("@cotal-ai/core").RemoteManagerGoalIndexScanRequest;
|
|
264
|
+
}) => ReturnType<AuthAuthorityPlane["scanManagerGoalIndex"]>;
|
|
265
|
+
authorizeManagerAdmin: (args: HumanHolder & {
|
|
266
|
+
request: RemoteManagerAdminAuthorizationRequest;
|
|
267
|
+
}) => ReturnType<AuthAuthorityPlane["authorizeManagerAdmin"]>;
|
|
268
|
+
admitManagerRun: (args: HumanHolder & {
|
|
269
|
+
request: unknown;
|
|
270
|
+
}) => ReturnType<AuthAuthorityPlane["admitManagerRun"]>;
|
|
271
|
+
issueManagerRunAttempt: (args: HumanHolder & {
|
|
272
|
+
request: unknown;
|
|
273
|
+
}) => ReturnType<AuthAuthorityPlane["issueManagerRunAttempt"]>;
|
|
233
274
|
secrets: SecretStore;
|
|
234
275
|
retireInteractiveLifecycle: AuthAuthorityPlane["retireInteractiveLifecycle"];
|
|
235
276
|
retireManagedLifecycle: AuthAuthorityPlane["retireManagedLifecycle"];
|
package/dist/service.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
|
package/dist/service.js
CHANGED
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
*
|
|
19
19
|
* The exchange surface is LOCAL-V1, hardened: loopback bind only; `POST /exchange` requires the
|
|
20
20
|
* per-start high-entropy capability (`Authorization: Bearer <cap>` — readable only from the 0600
|
|
21
|
-
* discovery file, so same-user file ACL is the boundary
|
|
21
|
+
* discovery file, so same-user file ACL is the boundary, or from a hosted context's handle inside
|
|
22
|
+
* the host process); requests carrying an `Origin` header are
|
|
22
23
|
* rejected (a browser page can reach loopback; it must not be able to drive the exchange); bodies
|
|
23
24
|
* must be `application/json`; failed exchanges are rate-limited and logged. No CORS headers, ever.
|
|
24
25
|
*
|
|
@@ -61,7 +62,8 @@ import { Kvm } from "@nats-io/kv";
|
|
|
61
62
|
import { contractRefToHex, contractStoreContext, 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, authorizeServeGrant, contractArtifactCanonicalBytes, DEV_OWNER, endpointRegistrationBarrier, mintLifecycleUid, principalKey, provisionEndpointGateOpen, publishContractArtifact, registerServiceInstance, SERVICE_READY, writeServiceStatus } from "@cotal-ai/core";
|
|
62
63
|
import { findCotalRoot, loadManagerInstanceIdentity, userAuthStateDir, workspaceSecretStore, createAuthInstanceIdentity, loadAuthInstanceIdentity } from "@cotal-ai/workspace";
|
|
63
64
|
import { decodeJwt } from "jose";
|
|
64
|
-
import { deriveOwnerForIdpSubject } from "./derive.js";
|
|
65
|
+
import { deriveOwnerForIdpSubject, platformControlOwner } from "./derive.js";
|
|
66
|
+
import { makePlatformControlAuthority, requireManagerAuthorityHolder } from "./platform-control.js";
|
|
65
67
|
import { startAuthCallout } from "./callout.js";
|
|
66
68
|
import { createIdpBridge, verifyIdpToken } from "./idp.js";
|
|
67
69
|
import { PUBLIC_EXCHANGE_VIEWS } from "./token.js";
|
|
@@ -617,13 +619,12 @@ export async function openAuthAuthorityPlane(opts) {
|
|
|
617
619
|
await flight;
|
|
618
620
|
return { retired: true, lifecycleUid };
|
|
619
621
|
},
|
|
620
|
-
issueManagerServiceAuthority: async (
|
|
622
|
+
issueManagerServiceAuthority: async (holder) => {
|
|
621
623
|
refuseIfFenced();
|
|
624
|
+
const { owner } = holder;
|
|
622
625
|
const observeManagerGate = async (instanceId) => (await serveIssuanceGateKv(await new Kvm(remoteIssuer.nc).open(epAuthBucket(space)), space, { endpoint: "manager", instanceId }).observe()) ?? null;
|
|
623
626
|
return issueRemoteManagerAuthority({
|
|
624
|
-
|
|
625
|
-
scope,
|
|
626
|
-
request,
|
|
627
|
+
...holder,
|
|
627
628
|
authorizeRenewal: ({ owner: o, request: r }) => authorizeRemoteManagerRenewal({
|
|
628
629
|
request: r, owner: o, space, accountPublicKey: dataAccount.pub, proofSecret: dataAccount.signingSeed,
|
|
629
630
|
observeManagerGate,
|
|
@@ -821,14 +822,13 @@ export async function openAuthAuthorityPlane(opts) {
|
|
|
821
822
|
},
|
|
822
823
|
});
|
|
823
824
|
},
|
|
824
|
-
maintainRemoteManager: async (
|
|
825
|
+
maintainRemoteManager: async (holder) => {
|
|
825
826
|
refuseIfFenced();
|
|
827
|
+
const { owner } = holder;
|
|
826
828
|
const gateKv = await new Kvm(remoteIssuer.nc).open(epAuthBucket(space));
|
|
827
829
|
const authorized = await authorizeRemoteManagerMaintenance({
|
|
828
|
-
|
|
829
|
-
scope,
|
|
830
|
+
...holder,
|
|
830
831
|
space,
|
|
831
|
-
request,
|
|
832
832
|
scanner,
|
|
833
833
|
observeManagerGate: async (instanceId) => serveIssuanceGateKv(gateKv, space, { endpoint: "manager", instanceId }).observe(),
|
|
834
834
|
});
|
|
@@ -876,14 +876,12 @@ export async function openAuthAuthorityPlane(opts) {
|
|
|
876
876
|
}
|
|
877
877
|
return completeRemoteManagerMaintenance(authorized, owner, { reconciliation: report });
|
|
878
878
|
},
|
|
879
|
-
validateRetainedAgent: async (
|
|
879
|
+
validateRetainedAgent: async (holder) => {
|
|
880
880
|
refuseIfFenced();
|
|
881
881
|
return authorizeRemoteRetainedAgentValidation({
|
|
882
|
-
|
|
883
|
-
scope,
|
|
882
|
+
...holder,
|
|
884
883
|
proofSecret: dataAccount.signingSeed,
|
|
885
884
|
space,
|
|
886
|
-
request,
|
|
887
885
|
observeManagerGate: async (instanceId) => {
|
|
888
886
|
const gate = serveIssuanceGateKv(await new Kvm(remoteIssuer.nc).open(epAuthBucket(space)), space, { endpoint: "manager", instanceId });
|
|
889
887
|
return gate.observe();
|
|
@@ -934,10 +932,11 @@ export async function openAuthAuthorityPlane(opts) {
|
|
|
934
932
|
? authorizeRemoteManagedAgentRuntimeStatus({ ...args, request })
|
|
935
933
|
: authorizeRemoteManagedAgentRuntimeCreate({ ...args, request });
|
|
936
934
|
},
|
|
937
|
-
scanManagerGoalIndex: async (
|
|
935
|
+
scanManagerGoalIndex: async (holder) => {
|
|
938
936
|
refuseIfFenced();
|
|
937
|
+
const { owner } = holder;
|
|
939
938
|
const authorized = await authorizeRemoteManagerGoalIndexScan({
|
|
940
|
-
|
|
939
|
+
...holder, proofSecret: dataAccount.signingSeed, space,
|
|
941
940
|
observeManagerGate: async (instanceId) => {
|
|
942
941
|
const gate = serveIssuanceGateKv(await new Kvm(remoteIssuer.nc).open(epAuthBucket(space)), space, { endpoint: "manager", instanceId });
|
|
943
942
|
return gate.observe();
|
|
@@ -945,11 +944,11 @@ export async function openAuthAuthorityPlane(opts) {
|
|
|
945
944
|
});
|
|
946
945
|
return completeRemoteManagerGoalIndexScan(authorized, owner, await recordsScanner.scanManagerGoalIndex(owner));
|
|
947
946
|
},
|
|
948
|
-
authorizeManagerAdmin: async ({
|
|
947
|
+
authorizeManagerAdmin: async ({ request, ...holder }) => {
|
|
949
948
|
refuseIfFenced();
|
|
950
949
|
return authorizeRemoteManagerAdmin({
|
|
951
|
-
managerOwner: owner,
|
|
952
|
-
managerScope: scope,
|
|
950
|
+
managerOwner: holder.owner,
|
|
951
|
+
...(holder.holder === "platform" ? { managerAssignment: holder.assignment } : { managerScope: holder.scope }),
|
|
953
952
|
proofSecret: dataAccount.signingSeed,
|
|
954
953
|
space,
|
|
955
954
|
dir: opts.dir,
|
|
@@ -960,10 +959,10 @@ export async function openAuthAuthorityPlane(opts) {
|
|
|
960
959
|
},
|
|
961
960
|
});
|
|
962
961
|
},
|
|
963
|
-
admitManagerRun: async ({
|
|
962
|
+
admitManagerRun: async ({ request, ...holder }) => {
|
|
964
963
|
refuseIfFenced();
|
|
965
|
-
|
|
966
|
-
|
|
964
|
+
const { owner } = holder;
|
|
965
|
+
requireManagerAuthorityHolder(holder, String(request?.instanceId), 'manager run admission needs scope "supervise"; spawn/admin do not imply it');
|
|
967
966
|
const runId = parseRemoteRunAdmissionRequest(request).run.runId;
|
|
968
967
|
const hostAuth = {
|
|
969
968
|
space,
|
|
@@ -997,10 +996,10 @@ export async function openAuthAuthorityPlane(opts) {
|
|
|
997
996
|
}
|
|
998
997
|
});
|
|
999
998
|
},
|
|
1000
|
-
issueManagerRunAttempt: async ({
|
|
999
|
+
issueManagerRunAttempt: async ({ request, ...holder }) => {
|
|
1001
1000
|
refuseIfFenced();
|
|
1002
|
-
|
|
1003
|
-
|
|
1001
|
+
const { owner } = holder;
|
|
1002
|
+
requireManagerAuthorityHolder(holder, String(request?.instanceId), 'manager run attempt needs scope "supervise"; spawn/admin do not imply it');
|
|
1004
1003
|
const req = parseRemoteRunAttemptRequest(request);
|
|
1005
1004
|
const recordsKv = await openRecordsBucket(remoteIssuer.nc, space);
|
|
1006
1005
|
const grant = await authorizeRemoteRunAttempt({
|
|
@@ -1078,6 +1077,12 @@ export async function openAuthAuthorityPlane(opts) {
|
|
|
1078
1077
|
credentials: { operator },
|
|
1079
1078
|
};
|
|
1080
1079
|
},
|
|
1080
|
+
observeManagerInstance: async (instanceId) => {
|
|
1081
|
+
refuseIfFenced();
|
|
1082
|
+
const gate = await serveIssuanceGateKv(await new Kvm(remoteIssuer.nc).open(epAuthBucket(space)), space, { endpoint: "manager", instanceId }).observe();
|
|
1083
|
+
const rec = await readSvcRecordLeader(recordsJsm, space, recordSpecKey(RECORD_KINDS.svc, ["manager", instanceId]));
|
|
1084
|
+
return { registered: rec !== undefined && !("deleted" in rec), gate: gate ?? null };
|
|
1085
|
+
},
|
|
1081
1086
|
fenced,
|
|
1082
1087
|
close: async () => {
|
|
1083
1088
|
// Clean-close order (SPEC 13.13): the rail stops answering first, then scan-capable
|
|
@@ -1188,27 +1193,19 @@ export async function runAuthService(args, store) {
|
|
|
1188
1193
|
if (publicPort !== undefined && (!Number.isInteger(publicPort) || publicPort < 0 || publicPort > 65535))
|
|
1189
1194
|
throw new Error(`auth-service: --exchange-public-port must be a port number, got "${publicPortRaw}"`);
|
|
1190
1195
|
const publicUrlFlag = v["exchange-public-url"];
|
|
1191
|
-
if (publicUrlFlag !== undefined && !/^https:\/\//.test(publicUrlFlag))
|
|
1192
|
-
throw new Error(`auth-service: --exchange-public-url must be an https:// URL (TLS terminates at the reverse proxy), got "${publicUrlFlag}"`);
|
|
1193
1196
|
const trustedProxy = v["exchange-trusted-proxy"] !== undefined;
|
|
1194
1197
|
if (publicPort === undefined && (publicUrlFlag !== undefined || trustedProxy))
|
|
1195
1198
|
throw new Error("auth-service: --exchange-public-url/--exchange-trusted-proxy require --exchange-public-port");
|
|
1196
1199
|
const advertisedServer = v["advertised-server"];
|
|
1197
1200
|
if (advertisedServer !== undefined && publicPort === undefined)
|
|
1198
1201
|
throw new Error("auth-service: --advertised-server rides the public bundle - it requires --exchange-public-port");
|
|
1199
|
-
if (advertisedServer !== undefined) {
|
|
1200
|
-
const badAdvertised = checkAdvertisedServer(advertisedServer);
|
|
1201
|
-
if (badAdvertised)
|
|
1202
|
-
throw new Error(badAdvertised);
|
|
1203
|
-
}
|
|
1204
1202
|
const agentProvisioningUrl = v["agent-provisioning-url"];
|
|
1205
1203
|
if (agentProvisioningUrl !== undefined && publicPort === undefined)
|
|
1206
1204
|
throw new Error("auth-service: --agent-provisioning-url rides the public bundle - it requires --exchange-public-port");
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
}
|
|
1205
|
+
const publicFace = publicPort === undefined ? undefined : { port: publicPort, url: publicUrlFlag, trustedProxy, advertisedServer, agentProvisioningUrl };
|
|
1206
|
+
const badFace = publicFace && checkPublicFace(publicFace);
|
|
1207
|
+
if (badFace)
|
|
1208
|
+
throw new Error(badFace);
|
|
1212
1209
|
// The provider's space-scoped state dir for NON-SEAM material (ledger, IdP pin, discovery). The
|
|
1213
1210
|
// layout fact is workspace-owned (userAuthStateDir); this daemon never touches `.cotal/auth/auth.json`.
|
|
1214
1211
|
const root = findCotalRoot();
|
|
@@ -1238,14 +1235,15 @@ export async function runAuthService(args, store) {
|
|
|
1238
1235
|
dir,
|
|
1239
1236
|
secrets,
|
|
1240
1237
|
hostedStore: store !== undefined,
|
|
1241
|
-
...(
|
|
1238
|
+
...(publicFace !== undefined ? { publicFace } : {}),
|
|
1242
1239
|
// The CLI composition's local manager is this workspace root's persisted instance, re-read per
|
|
1243
1240
|
// selection exactly as before. A hosted context passes no local manager at all.
|
|
1244
1241
|
localManager: () => loadManagerInstanceIdentity(root, space),
|
|
1245
1242
|
});
|
|
1246
1243
|
// All planes bound — NOW write the discovery file (its existence is the readiness signal).
|
|
1247
|
-
|
|
1248
|
-
|
|
1244
|
+
const { url, publicUrl, cap } = started.handle;
|
|
1245
|
+
saveAuthServiceInfo(dir, { url, pid: process.pid, cap, ...(publicUrl !== undefined ? { publicUrl } : {}) });
|
|
1246
|
+
console.log(`✓ auth service up (space ${space}) - callout on ${server}, exchange/JWKS at ${url}${publicUrl !== undefined ? `, public exchange at ${publicUrl}` : ""}`);
|
|
1249
1247
|
// The CLI wrapper, not the context, owns process signals and exit codes.
|
|
1250
1248
|
const stop = async () => {
|
|
1251
1249
|
clearAuthServiceInfo(dir); // a dead service must not satisfy the next start's readiness poll
|
|
@@ -1288,6 +1286,11 @@ export async function startAuthService(inputs) {
|
|
|
1288
1286
|
const port = inputs.port ?? 0;
|
|
1289
1287
|
if (!Number.isInteger(port) || port < 0 || port > 65535)
|
|
1290
1288
|
throw new Error(`auth-service: port must be a port number, got ${port}`);
|
|
1289
|
+
if (inputs.platformControl !== undefined && typeof inputs.platformControl?.observeAssignment !== "function")
|
|
1290
|
+
throw new Error("auth-service: platformControl requires an observeAssignment function");
|
|
1291
|
+
const badFace = inputs.publicFace && checkPublicFace(inputs.publicFace);
|
|
1292
|
+
if (badFace)
|
|
1293
|
+
throw new Error(badFace);
|
|
1291
1294
|
const started = await startAuthContext({
|
|
1292
1295
|
space: inputs.space,
|
|
1293
1296
|
server: inputs.servers,
|
|
@@ -1297,6 +1300,9 @@ export async function startAuthService(inputs) {
|
|
|
1297
1300
|
hostedStore: true,
|
|
1298
1301
|
localManager: () => undefined,
|
|
1299
1302
|
context: inputs.context,
|
|
1303
|
+
...(inputs.publicFace !== undefined ? { publicFace: inputs.publicFace } : {}),
|
|
1304
|
+
...(inputs.platformControl !== undefined ? { platformControl: inputs.platformControl } : {}),
|
|
1305
|
+
...(inputs.standingRenewableTtlSeconds !== undefined ? { standingRenewableTtlSeconds: inputs.standingRenewableTtlSeconds } : {}),
|
|
1300
1306
|
});
|
|
1301
1307
|
return started.handle;
|
|
1302
1308
|
}
|
|
@@ -1332,6 +1338,7 @@ async function startAuthContext(o) {
|
|
|
1332
1338
|
dataAccount: { pub: keys.dataAccount.pub, signingSeed: keys.dataAccount.signingSeed },
|
|
1333
1339
|
log: (l) => console.error(l),
|
|
1334
1340
|
localManager: o.localManager,
|
|
1341
|
+
...(o.standingRenewableTtlSeconds !== undefined ? { standingRenewableTtlSeconds: o.standingRenewableTtlSeconds } : {}),
|
|
1335
1342
|
});
|
|
1336
1343
|
let nc;
|
|
1337
1344
|
let http;
|
|
@@ -1444,7 +1451,7 @@ async function startAuthContext(o) {
|
|
|
1444
1451
|
});
|
|
1445
1452
|
const paddr = pub.address();
|
|
1446
1453
|
const boundPublic = typeof paddr === "object" && paddr ? paddr.port : face.port;
|
|
1447
|
-
publicUrl = face.
|
|
1454
|
+
publicUrl = face.url ?? `http://127.0.0.1:${boundPublic}`;
|
|
1448
1455
|
finalizeUserBundleEndpoint(bundle, publicUrl);
|
|
1449
1456
|
}
|
|
1450
1457
|
const callNc = nc;
|
|
@@ -1476,9 +1483,47 @@ async function startAuthContext(o) {
|
|
|
1476
1483
|
return end;
|
|
1477
1484
|
});
|
|
1478
1485
|
const context = o.context ?? { accountPublicKey: keys.dataAccount.pub, lifecycleUid: "" };
|
|
1486
|
+
const platformControl = o.platformControl;
|
|
1487
|
+
// The human route's retained-validation composition, for the platform holder.
|
|
1488
|
+
const validateRetainedForHolder = async (holder, request) => {
|
|
1489
|
+
const retained = await plane.validateRetainedAgent({ ...holder, request });
|
|
1490
|
+
const authority = await validateRetainedManagedAgent({
|
|
1491
|
+
store: secrets,
|
|
1492
|
+
dir,
|
|
1493
|
+
space,
|
|
1494
|
+
owner: retained.target.owner,
|
|
1495
|
+
actor: retained.target.actor,
|
|
1496
|
+
actorToken: retained.actorToken,
|
|
1497
|
+
sentinelCreds: retained.sentinelCreds,
|
|
1498
|
+
});
|
|
1499
|
+
return completeRemoteRetainedAgentValidation(retained, holder.owner, authority);
|
|
1500
|
+
};
|
|
1479
1501
|
const service = {
|
|
1480
1502
|
url,
|
|
1481
1503
|
...(publicUrl !== undefined ? { publicUrl } : {}),
|
|
1504
|
+
cap,
|
|
1505
|
+
...(platformControl !== undefined ? {
|
|
1506
|
+
platformControlAuthority: makePlatformControlAuthority({
|
|
1507
|
+
space,
|
|
1508
|
+
accountPublicKey: keys.dataAccount.pub,
|
|
1509
|
+
owner: platformControlOwner(ownerSecret, space, keys.dataAccount.pub),
|
|
1510
|
+
observeAssignment: (s, a) => platformControl.observeAssignment(s, a),
|
|
1511
|
+
observeManagerInstance: plane.observeManagerInstance,
|
|
1512
|
+
dispatch: (holder, request) => {
|
|
1513
|
+
if (state !== "ready" || closePromise !== undefined)
|
|
1514
|
+
throw new EpEnvelopeError("unavailable", "auth-service context is not ready");
|
|
1515
|
+
switch (request.kind) {
|
|
1516
|
+
case "manager-service-authority": return plane.issueManagerServiceAuthority({ ...holder, request });
|
|
1517
|
+
case "manager-service-maintenance": return plane.maintainRemoteManager({ ...holder, request });
|
|
1518
|
+
case "manager-goal-index-scan": return plane.scanManagerGoalIndex({ ...holder, request });
|
|
1519
|
+
case "manager-admin-authorization": return plane.authorizeManagerAdmin({ ...holder, request });
|
|
1520
|
+
case "manager-run-admission": return plane.admitManagerRun({ ...holder, request });
|
|
1521
|
+
case "manager-run-attempt": return plane.issueManagerRunAttempt({ ...holder, request });
|
|
1522
|
+
case "manager-retained-agent-validation": return validateRetainedForHolder(holder, request);
|
|
1523
|
+
}
|
|
1524
|
+
},
|
|
1525
|
+
}),
|
|
1526
|
+
} : {}),
|
|
1482
1527
|
readiness() {
|
|
1483
1528
|
if (state === "unavailable")
|
|
1484
1529
|
return { state, context, cause: cause ?? "auth-service context is unavailable" };
|
|
@@ -1487,7 +1532,7 @@ async function startAuthContext(o) {
|
|
|
1487
1532
|
drain: close,
|
|
1488
1533
|
close,
|
|
1489
1534
|
};
|
|
1490
|
-
return {
|
|
1535
|
+
return { handle: service, ended };
|
|
1491
1536
|
}
|
|
1492
1537
|
catch (e) {
|
|
1493
1538
|
// A failed start releases only what THIS context acquired, in reverse order.
|
|
@@ -2009,6 +2054,16 @@ export function checkAdvertisedServer(raw) {
|
|
|
2009
2054
|
return `auth-service: --advertised-server must be a broker URL (nats://, tls://, ws:// or wss://), got ${u.protocol}//`;
|
|
2010
2055
|
return undefined;
|
|
2011
2056
|
}
|
|
2057
|
+
/** The public face's value rules, one set for the CLI flags and the hosted input. A public face
|
|
2058
|
+
* without a port has no listener for the rest to apply to. */
|
|
2059
|
+
function checkPublicFace(face) {
|
|
2060
|
+
if (!Number.isInteger(face.port) || face.port < 0 || face.port > 65535)
|
|
2061
|
+
return `auth-service: a public face needs a port number, got ${face.port}`;
|
|
2062
|
+
if (face.url !== undefined && !/^https:\/\//.test(face.url))
|
|
2063
|
+
return `auth-service: --exchange-public-url must be an https:// URL (TLS terminates at the reverse proxy), got "${face.url}"`;
|
|
2064
|
+
return (face.advertisedServer !== undefined ? checkAdvertisedServer(face.advertisedServer) : undefined)
|
|
2065
|
+
?? (face.agentProvisioningUrl !== undefined ? checkAgentProvisioningUrl(face.agentProvisioningUrl) : undefined);
|
|
2066
|
+
}
|
|
2012
2067
|
/** Compose the user bundle the public face serves at /.well-known/cotal-mesh. ONE producer,
|
|
2013
2068
|
* exported so the consumer contract (`checkUserBundle` in the CLI) can be asserted against the
|
|
2014
2069
|
* real composition rather than a copy. The trust pins ride a `userAuth` arm because that is the
|