@agentproto/auth 1.1.2 → 1.2.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/README.md +43 -0
- package/dist/index.d.ts +144 -4
- package/dist/index.mjs +106 -10
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -233,6 +233,47 @@ exposure and have `resolveMcpHeaderExposure(exposure, broker)` lay brokered
|
|
|
233
233
|
headers onto the transport. `secrets` keeps **zero dependency** on `auth`
|
|
234
234
|
through that structural seam. See `@agentproto/secrets`' README.
|
|
235
235
|
|
|
236
|
+
## Sub-accounts
|
|
237
|
+
|
|
238
|
+
An *account* (a login or billing identity) can have *sub-accounts* — orgs,
|
|
239
|
+
workspaces, projects — each with its own quota. A profile pins one with the
|
|
240
|
+
optional `subaccount` field, so every pin is a distinct, truthful wallet:
|
|
241
|
+
|
|
242
|
+
```jsonc
|
|
243
|
+
{ "id": "acme-ws01", "endpoint": "<endpoint>", "method": "api-key",
|
|
244
|
+
"source": "<account-source>", "subaccount": { "kind": "org", "id": "org_01ABC", "name": "Ws01" } }
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
`kind` is `[a-z][a-z0-9-]*`; `id` is opaque; `name` is a display label used in
|
|
248
|
+
usage-limit tags. The field is optional and the on-disk store format is
|
|
249
|
+
unchanged. CLI: `agentproto auth profile create <id> --subaccount <kind>:<id>`
|
|
250
|
+
and `agentproto auth subaccounts list <profile|account> [--create [--prefix]]`.
|
|
251
|
+
|
|
252
|
+
How a pin is *applied* belongs to a provider, never to this package or the
|
|
253
|
+
runtime. A provider implements `SubaccountProvider` and is added with
|
|
254
|
+
`registerSubaccountProvider`:
|
|
255
|
+
|
|
256
|
+
| Member | Purpose |
|
|
257
|
+
| --- | --- |
|
|
258
|
+
| `id`, `source?`, `endpoints?`, `kinds` | identity, and which accounts it owns (by `source` name, else by endpoint) |
|
|
259
|
+
| `list(account)` | discovery: `{ account, subaccounts: [{kind, id, name}] }` |
|
|
260
|
+
| `resolve(profile, { credential? })` | spawn time: `{ credential?, credentialEnvOverride?, env?, isolateDataHome? }` |
|
|
261
|
+
| `migrateLegacySource?(source)` | read-time migration of a pre-pin provider-encoded `source` into the pin |
|
|
262
|
+
|
|
263
|
+
A provider throws `SubaccountError` when a pin cannot be listed or resolved; the
|
|
264
|
+
runtime fails the spawn loudly rather than falling back to the account's default
|
|
265
|
+
scope. Providers ship with their adapter and the host registers them (the CLI
|
|
266
|
+
does so for the built-ins).
|
|
267
|
+
|
|
268
|
+
The registry is process-global and starts EMPTY: a host that uses
|
|
269
|
+
`@agentproto/auth` outside the CLI must call `registerSubaccountProvider` for
|
|
270
|
+
each provider it needs BEFORE creating, reading or spawning pinned profiles.
|
|
271
|
+
Until then, creating a profile with a legacy `opencode-console:<orgId>` source is
|
|
272
|
+
rejected, and a spawn on a pinned profile whose provider is not registered fails
|
|
273
|
+
with `auth_source_unresolved` (it never runs on the account's default scope). A
|
|
274
|
+
pin on a credential-backed profile is accepted at create time even when no
|
|
275
|
+
provider owns its endpoint yet; the clear error comes at spawn time.
|
|
276
|
+
|
|
236
277
|
## API surface
|
|
237
278
|
|
|
238
279
|
| Export | Purpose |
|
|
@@ -249,6 +290,8 @@ through that structural seam. See `@agentproto/secrets`' README.
|
|
|
249
290
|
| `KeychainStore` / `MemoryStore` / `FileStore` / `resolveStoreRef` | built-in backends + ref resolver |
|
|
250
291
|
| `readKeychainToken` / `writeKeychainToken` / `resolveAccount` | Keychain helpers |
|
|
251
292
|
| `guildeAuthProvider` / `BUILTIN_AUTH_PROVIDERS` | shipped builtins |
|
|
293
|
+
| `registerSubaccountProvider` / `findSubaccountProvider` / `listSubaccountProviders` | sub-account provider registry |
|
|
294
|
+
| `SubaccountProvider` / `SubaccountPin` / `SubaccountError` / `parseSubaccountPin` | sub-account contract |
|
|
252
295
|
|
|
253
296
|
## License
|
|
254
297
|
|
package/dist/index.d.ts
CHANGED
|
@@ -609,6 +609,15 @@ interface CostBudget {
|
|
|
609
609
|
/** Which spend surface the window is summed over. See {@link CostBudgetScope}. */
|
|
610
610
|
scope: CostBudgetScope;
|
|
611
611
|
}
|
|
612
|
+
/** A pinned sub-account of the profile's account: `kind` is free-form (`org`,
|
|
613
|
+
* `workspace`, `project`, …) and only meaningful to the provider that owns the
|
|
614
|
+
* account (see `subaccounts.ts`). */
|
|
615
|
+
interface SubaccountPin {
|
|
616
|
+
kind: string;
|
|
617
|
+
id: string;
|
|
618
|
+
/** Human-readable name captured at discovery time; informational only. */
|
|
619
|
+
name?: string;
|
|
620
|
+
}
|
|
612
621
|
/** A named, billing-endpoint-scoped credential reference. */
|
|
613
622
|
interface AuthProfile {
|
|
614
623
|
/** Stable id, unique across all profiles (the `profileRef` a session
|
|
@@ -635,6 +644,13 @@ interface AuthProfile {
|
|
|
635
644
|
* fresh at spawn time instead. Mutually exclusive with
|
|
636
645
|
* {@link credentialRef}. */
|
|
637
646
|
source?: string;
|
|
647
|
+
/** Pins one SUB-ACCOUNT (org / workspace / project / team) of the account this
|
|
648
|
+
* profile authenticates as — the account being the {@link credentialRef}'d
|
|
649
|
+
* secret or the {@link source}. Each pin is its own wallet; how it is
|
|
650
|
+
* applied at spawn is the registered provider's business (`subaccounts.ts`).
|
|
651
|
+
* ABSENT ⇒ the account's default scope, byte-identical to a profile that
|
|
652
|
+
* predates this field. */
|
|
653
|
+
subaccount?: SubaccountPin;
|
|
638
654
|
/** Optional human-readable name ("Jeremy Max", "work OpenRouter"). */
|
|
639
655
|
label?: string;
|
|
640
656
|
/** Whole-profile enable/disable. ABSENT (or `false`) ⇒ enabled (today's
|
|
@@ -665,6 +681,114 @@ interface AuthProfile {
|
|
|
665
681
|
origin?: string;
|
|
666
682
|
}
|
|
667
683
|
|
|
684
|
+
/**
|
|
685
|
+
* Sub-accounts: an ACCOUNT (a login / billing identity) can have SUB-ACCOUNTS
|
|
686
|
+
* (org, workspace, project, team) with their own quota and billing. A profile
|
|
687
|
+
* can pin one ({@link AuthProfile.subaccount}); each pin is a distinct,
|
|
688
|
+
* truthful wallet. HOW a pin is applied to a spawn — headers, an inline config
|
|
689
|
+
* block, a scoped token, an isolated data home — is the provider's business.
|
|
690
|
+
*
|
|
691
|
+
* This module is the generic seam: the pin type, the {@link SubaccountProvider}
|
|
692
|
+
* interface, and a process-wide registry. Nothing here (or in any core spawn
|
|
693
|
+
* path) names a vendor; providers live with their adapter and are registered by
|
|
694
|
+
* the host (the CLI registers the built-ins at start-up).
|
|
695
|
+
*/
|
|
696
|
+
|
|
697
|
+
/** Conservative charset for a pin's `kind` — it ends up in CLI args and logs. */
|
|
698
|
+
declare const SUBACCOUNT_KIND_RE: RegExp;
|
|
699
|
+
/** `"org:org_01ABC"` → `{ kind: "org", id: "org_01ABC" }`; split on the FIRST
|
|
700
|
+
* colon so an id may itself contain colons. Returns undefined when malformed. */
|
|
701
|
+
declare function parseSubaccountPin(spec: string): SubaccountPin | undefined;
|
|
702
|
+
/** The parent account a provider lists sub-accounts of. */
|
|
703
|
+
interface SubaccountAccountRef {
|
|
704
|
+
/** Billing endpoint the account authenticates against (`opencode-go`, …). */
|
|
705
|
+
endpoint: string;
|
|
706
|
+
/** Source-backed account (the account name a provider owns), no stored secret. */
|
|
707
|
+
source?: string;
|
|
708
|
+
/** Credential-backed account: the resolved secret. Never logged or returned. */
|
|
709
|
+
credential?: string;
|
|
710
|
+
}
|
|
711
|
+
interface DiscoveredSubaccount {
|
|
712
|
+
kind: string;
|
|
713
|
+
id: string;
|
|
714
|
+
name: string;
|
|
715
|
+
}
|
|
716
|
+
interface SubaccountListing {
|
|
717
|
+
account: {
|
|
718
|
+
id: string;
|
|
719
|
+
label?: string;
|
|
720
|
+
};
|
|
721
|
+
subaccounts: DiscoveredSubaccount[];
|
|
722
|
+
}
|
|
723
|
+
/** What a provider hands the spawn path for one pinned profile. */
|
|
724
|
+
interface SubaccountResolution {
|
|
725
|
+
/** Credential to inject, when the provider resolves its own (a source-backed
|
|
726
|
+
* account's scoped token). Omitted ⇒ the profile's stored credential stands. */
|
|
727
|
+
credential?: string;
|
|
728
|
+
/** Env var the credential is set into INSTEAD of the endpoint's conventional
|
|
729
|
+
* key env (the conventional one is then scrubbed). */
|
|
730
|
+
credentialEnvOverride?: string;
|
|
731
|
+
/** Extra env set verbatim beside the credential. A value that is a JSON
|
|
732
|
+
* object is deep-merged over a same-key value the spawn already carries
|
|
733
|
+
* (e.g. a mode's inline config), never clobbering it. */
|
|
734
|
+
env?: Record<string, string>;
|
|
735
|
+
/** `false` opts out of the adapter's isolated, login-less data home for this
|
|
736
|
+
* spawn; omitted ⇒ whatever the adapter declares applies. */
|
|
737
|
+
isolateDataHome?: boolean;
|
|
738
|
+
}
|
|
739
|
+
/** Raised by a provider when a sub-account cannot be listed or resolved. The
|
|
740
|
+
* runtime maps it onto its own spawn-error codes; the message must never carry
|
|
741
|
+
* a secret. */
|
|
742
|
+
declare class SubaccountError extends Error {
|
|
743
|
+
constructor(message: string);
|
|
744
|
+
}
|
|
745
|
+
interface SubaccountProvider {
|
|
746
|
+
/** Registry key, unique per provider. */
|
|
747
|
+
id: string;
|
|
748
|
+
/** The `source` name that identifies this provider's source-backed accounts
|
|
749
|
+
* (`AuthProfile.source`). */
|
|
750
|
+
source?: string;
|
|
751
|
+
/** Endpoints whose credential-backed profiles this provider serves. */
|
|
752
|
+
endpoints?: readonly string[];
|
|
753
|
+
/** Sub-account kinds this provider understands. */
|
|
754
|
+
kinds: readonly string[];
|
|
755
|
+
/** Endpoint a profile created from a discovered sub-account lands on. */
|
|
756
|
+
defaultEndpoint?: string;
|
|
757
|
+
/** Default id prefix for profiles created from a discovery (`<prefix>-<name>`). */
|
|
758
|
+
profilePrefix?: string;
|
|
759
|
+
/** Discovery: the sub-accounts of `account`. */
|
|
760
|
+
list(account: SubaccountAccountRef): Promise<SubaccountListing>;
|
|
761
|
+
/** Spawn-time: how the pinned `profile` is applied. `credential` is the
|
|
762
|
+
* profile's stored credential when it has one. */
|
|
763
|
+
resolve(profile: AuthProfile & {
|
|
764
|
+
subaccount: SubaccountPin;
|
|
765
|
+
}, ctx: {
|
|
766
|
+
credential?: string;
|
|
767
|
+
}): Promise<SubaccountResolution>;
|
|
768
|
+
/** Migrate-on-read hook for a profile shape that predates generic pins: a
|
|
769
|
+
* legacy `source` string → the account `source` + the pin it encoded. */
|
|
770
|
+
migrateLegacySource?(source: string): SubaccountPin | undefined;
|
|
771
|
+
}
|
|
772
|
+
/** Register (or replace, by `id`) a provider. Idempotent. */
|
|
773
|
+
declare function registerSubaccountProvider(provider: SubaccountProvider): void;
|
|
774
|
+
/** Remove a provider; returns whether it was registered. Mainly for tests. */
|
|
775
|
+
declare function unregisterSubaccountProvider(id: string): boolean;
|
|
776
|
+
declare function listSubaccountProviders(): SubaccountProvider[];
|
|
777
|
+
declare function getSubaccountProvider(id: string): SubaccountProvider | undefined;
|
|
778
|
+
/** The provider owning an account: by `source` name first, else by `endpoint`
|
|
779
|
+
* for a credential-backed account. */
|
|
780
|
+
declare function findSubaccountProvider(account: {
|
|
781
|
+
source?: string;
|
|
782
|
+
endpoint?: string;
|
|
783
|
+
}): SubaccountProvider | undefined;
|
|
784
|
+
/**
|
|
785
|
+
* Migrate-on-read: a profile that carries a legacy provider-encoded `source`
|
|
786
|
+
* (and no `subaccount`) is returned with the generic shape — `source` reduced
|
|
787
|
+
* to the account name, the encoded pin lifted into `subaccount`. Any other
|
|
788
|
+
* profile is returned as-is. Pure over the registry; never writes.
|
|
789
|
+
*/
|
|
790
|
+
declare function migrateLegacySubaccountProfile(profile: AuthProfile): AuthProfile;
|
|
791
|
+
|
|
668
792
|
/**
|
|
669
793
|
* Named auth-profile store — CRUD over `~/.agentproto/auth-profiles.json`
|
|
670
794
|
* (mode 0600), generalizing `providers-store`'s single-key-per-provider file
|
|
@@ -692,6 +816,11 @@ declare const authProfilesFileSchema: z.ZodObject<{
|
|
|
692
816
|
}>;
|
|
693
817
|
credentialRef: z.ZodOptional<z.ZodString>;
|
|
694
818
|
source: z.ZodOptional<z.ZodString>;
|
|
819
|
+
subaccount: z.ZodOptional<z.ZodObject<{
|
|
820
|
+
kind: z.ZodString;
|
|
821
|
+
id: z.ZodString;
|
|
822
|
+
name: z.ZodOptional<z.ZodString>;
|
|
823
|
+
}, z.core.$strip>>;
|
|
695
824
|
label: z.ZodOptional<z.ZodString>;
|
|
696
825
|
disabled: z.ZodOptional<z.ZodBoolean>;
|
|
697
826
|
models: z.ZodOptional<z.ZodObject<{
|
|
@@ -716,6 +845,11 @@ declare const authProfilesFileSchema: z.ZodObject<{
|
|
|
716
845
|
method: "oauth-bearer" | "api-key";
|
|
717
846
|
credentialRef?: string | undefined;
|
|
718
847
|
source?: string | undefined;
|
|
848
|
+
subaccount?: {
|
|
849
|
+
kind: string;
|
|
850
|
+
id: string;
|
|
851
|
+
name?: string | undefined;
|
|
852
|
+
} | undefined;
|
|
719
853
|
label?: string | undefined;
|
|
720
854
|
disabled?: boolean | undefined;
|
|
721
855
|
models?: {
|
|
@@ -766,9 +900,9 @@ declare function removeAuthProfile(id: string): Promise<boolean>;
|
|
|
766
900
|
|
|
767
901
|
/** Input to {@link createAuthProfile}. `credential` is the raw secret — it is
|
|
768
902
|
* written to the store and NEVER returned. Exactly one of `credential` /
|
|
769
|
-
* `source` must be given for an `oauth-bearer` profile; `api-key`
|
|
770
|
-
*
|
|
771
|
-
*
|
|
903
|
+
* `source` must be given for an `oauth-bearer` profile; `api-key` requires
|
|
904
|
+
* `credential`, except for a `source` owned by a registered sub-account
|
|
905
|
+
* provider (an account resolved at spawn, pinned to a `subaccount`). */
|
|
772
906
|
interface CreateAuthProfileInput {
|
|
773
907
|
/** Stable id, unique across all profiles. */
|
|
774
908
|
id: string;
|
|
@@ -785,6 +919,9 @@ interface CreateAuthProfileInput {
|
|
|
785
919
|
* resolved fresh at spawn time instead. Mutually exclusive with
|
|
786
920
|
* `credential`. */
|
|
787
921
|
source?: string;
|
|
922
|
+
/** Pin one sub-account (org / workspace / project) of the account — the
|
|
923
|
+
* `credential` or the `source`. See `subaccounts.ts`. */
|
|
924
|
+
subaccount?: SubaccountPin;
|
|
788
925
|
/** Optional human-readable name. */
|
|
789
926
|
label?: string;
|
|
790
927
|
/** Optional explicit credential-store slot. Omitted ⇒ derived from
|
|
@@ -806,6 +943,8 @@ interface CreatedAuthProfile {
|
|
|
806
943
|
credentialRef?: string;
|
|
807
944
|
/** Set for a source-backed profile; absent for a credential-backed one. */
|
|
808
945
|
source?: string;
|
|
946
|
+
/** The pinned sub-account, when the profile has one. */
|
|
947
|
+
subaccount?: SubaccountPin;
|
|
809
948
|
label?: string;
|
|
810
949
|
/** Provenance stamped at import time, when given. */
|
|
811
950
|
origin?: string;
|
|
@@ -845,6 +984,7 @@ interface ValidatedCreateInput {
|
|
|
845
984
|
method: AuthMethod;
|
|
846
985
|
credential?: string;
|
|
847
986
|
source?: string;
|
|
987
|
+
subaccount?: SubaccountPin;
|
|
848
988
|
label?: string;
|
|
849
989
|
credentialRef?: string;
|
|
850
990
|
origin?: string;
|
|
@@ -1097,4 +1237,4 @@ declare const BUILTIN_AUTH_PROVIDERS: readonly AuthProviderHandle[];
|
|
|
1097
1237
|
declare const SPEC_NAME = "agentauth";
|
|
1098
1238
|
declare const SPEC_VERSION = "v1";
|
|
1099
1239
|
|
|
1100
|
-
export { type AdapterAuthManifest, type AuthConfig, type AuthMethod, type AuthProfile, AuthProfileValidationError, type AuthProfilesFile, type AuthProviderDefinition, type AuthProviderFrontmatter, type AuthProviderHandle, type AuthProviderManifest, BUILTIN_AUTH_PROVIDERS, CeremonyRequiredError, type CostBudget, type CostBudgetScope, type CreateAuthProfileInput, type CreatedAuthProfile, CredentialBroker, type CredentialBrokerOptions, type CredentialIdentity, type CredentialStore, type DeletedAuthProfile, type DeviceCodeAuthConfig, type DiscoveredEndpoints, DiscoveryError, FLOW_ENGINES, FileStore, type FlowEngine, type FlowId, type FlowResult, type FlowRunOptions, type InstallConfig, KeychainStore, MemoryStore, type ModelCuration, type PATAuthConfig, type ProfileProvisionDeps, type RefreshAuthProfileModelsResult, type RunFlowOptions, SPEC_NAME, SPEC_VERSION, type ServiceAuthConfig, type StoreRef, type StoredCredential, type TokenStoreSpec, type UpdateAuthProfileInput, type ValidatedCreateInput, addAuthProfile, authConfigSchema, authProfilesPath, authProviderFrontmatterSchema, createAuthProfile, credentialIdentity, defineAuthProvider, deleteAuthProfile, deleteKeychainToken, deriveCredentialRef, discoverEndpoints, eligibleProfiles, fingerprintCredential, getAuthProfile, getAuthProvider, guildeAuthProvider, installConfigSchema, listAuthProfiles, listAuthProviderIds, listAuthProviders, loadAuthProfiles, methodsPresentable, parseAuthProviderManifest, parseAuthProviderManifestRaw, readKeychainToken, refreshAuthProfileModels, registerAuthProvider, removeAuthProfile, resolveAccount, resolveEndpoint, resolveStoreRef, runAuthFlow, setAuthProfileEnabled, setAuthProfileModels, tokenStoreSpecSchema, updateAuthProfile, validateCreateInput, writeKeychainToken };
|
|
1240
|
+
export { type AdapterAuthManifest, type AuthConfig, type AuthMethod, type AuthProfile, AuthProfileValidationError, type AuthProfilesFile, type AuthProviderDefinition, type AuthProviderFrontmatter, type AuthProviderHandle, type AuthProviderManifest, BUILTIN_AUTH_PROVIDERS, CeremonyRequiredError, type CostBudget, type CostBudgetScope, type CreateAuthProfileInput, type CreatedAuthProfile, CredentialBroker, type CredentialBrokerOptions, type CredentialIdentity, type CredentialStore, type DeletedAuthProfile, type DeviceCodeAuthConfig, type DiscoveredEndpoints, type DiscoveredSubaccount, DiscoveryError, FLOW_ENGINES, FileStore, type FlowEngine, type FlowId, type FlowResult, type FlowRunOptions, type InstallConfig, KeychainStore, MemoryStore, type ModelCuration, type PATAuthConfig, type ProfileProvisionDeps, type RefreshAuthProfileModelsResult, type RunFlowOptions, SPEC_NAME, SPEC_VERSION, SUBACCOUNT_KIND_RE, type ServiceAuthConfig, type StoreRef, type StoredCredential, type SubaccountAccountRef, SubaccountError, type SubaccountListing, type SubaccountPin, type SubaccountProvider, type SubaccountResolution, type TokenStoreSpec, type UpdateAuthProfileInput, type ValidatedCreateInput, addAuthProfile, authConfigSchema, authProfilesPath, authProviderFrontmatterSchema, createAuthProfile, credentialIdentity, defineAuthProvider, deleteAuthProfile, deleteKeychainToken, deriveCredentialRef, discoverEndpoints, eligibleProfiles, findSubaccountProvider, fingerprintCredential, getAuthProfile, getAuthProvider, getSubaccountProvider, guildeAuthProvider, installConfigSchema, listAuthProfiles, listAuthProviderIds, listAuthProviders, listSubaccountProviders, loadAuthProfiles, methodsPresentable, migrateLegacySubaccountProfile, parseAuthProviderManifest, parseAuthProviderManifestRaw, parseSubaccountPin, readKeychainToken, refreshAuthProfileModels, registerAuthProvider, registerSubaccountProvider, removeAuthProfile, resolveAccount, resolveEndpoint, resolveStoreRef, runAuthFlow, setAuthProfileEnabled, setAuthProfileModels, tokenStoreSpecSchema, unregisterSubaccountProvider, updateAuthProfile, validateCreateInput, writeKeychainToken };
|
package/dist/index.mjs
CHANGED
|
@@ -1248,6 +1248,54 @@ var CredentialBroker = class {
|
|
|
1248
1248
|
return headers;
|
|
1249
1249
|
}
|
|
1250
1250
|
};
|
|
1251
|
+
|
|
1252
|
+
// src/subaccounts.ts
|
|
1253
|
+
var SUBACCOUNT_KIND_RE = /^[a-z][a-z0-9-]*$/;
|
|
1254
|
+
function parseSubaccountPin(spec) {
|
|
1255
|
+
const at = spec.indexOf(":");
|
|
1256
|
+
if (at <= 0) return void 0;
|
|
1257
|
+
const kind = spec.slice(0, at).trim();
|
|
1258
|
+
const id = spec.slice(at + 1).trim();
|
|
1259
|
+
if (!SUBACCOUNT_KIND_RE.test(kind) || id === "") return void 0;
|
|
1260
|
+
return { kind, id };
|
|
1261
|
+
}
|
|
1262
|
+
var SubaccountError = class extends Error {
|
|
1263
|
+
constructor(message) {
|
|
1264
|
+
super(message);
|
|
1265
|
+
this.name = "SubaccountError";
|
|
1266
|
+
}
|
|
1267
|
+
};
|
|
1268
|
+
var providers = /* @__PURE__ */ new Map();
|
|
1269
|
+
function registerSubaccountProvider(provider) {
|
|
1270
|
+
providers.set(provider.id, provider);
|
|
1271
|
+
}
|
|
1272
|
+
function unregisterSubaccountProvider(id) {
|
|
1273
|
+
return providers.delete(id);
|
|
1274
|
+
}
|
|
1275
|
+
function listSubaccountProviders() {
|
|
1276
|
+
return [...providers.values()];
|
|
1277
|
+
}
|
|
1278
|
+
function getSubaccountProvider(id) {
|
|
1279
|
+
return providers.get(id);
|
|
1280
|
+
}
|
|
1281
|
+
function findSubaccountProvider(account) {
|
|
1282
|
+
const all = listSubaccountProviders();
|
|
1283
|
+
if (account.source !== void 0) {
|
|
1284
|
+
return all.find((p) => p.source === account.source) ?? all.find((p) => p.migrateLegacySource?.(account.source) !== void 0);
|
|
1285
|
+
}
|
|
1286
|
+
if (account.endpoint !== void 0) return all.find((p) => p.endpoints?.includes(account.endpoint));
|
|
1287
|
+
return void 0;
|
|
1288
|
+
}
|
|
1289
|
+
function migrateLegacySubaccountProfile(profile) {
|
|
1290
|
+
if (profile.subaccount !== void 0 || profile.source === void 0) return profile;
|
|
1291
|
+
for (const provider of providers.values()) {
|
|
1292
|
+
const pin = provider.migrateLegacySource?.(profile.source);
|
|
1293
|
+
if (pin !== void 0 && provider.source !== void 0) {
|
|
1294
|
+
return { ...profile, source: provider.source, subaccount: pin };
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
return profile;
|
|
1298
|
+
}
|
|
1251
1299
|
var authMethodSchema = z.enum(["oauth-bearer", "api-key"]);
|
|
1252
1300
|
var modelCurationSchema = z.object({
|
|
1253
1301
|
mode: z.enum(["all", "allow"]),
|
|
@@ -1258,12 +1306,18 @@ var costBudgetSchema = z.object({
|
|
|
1258
1306
|
window: z.string(),
|
|
1259
1307
|
scope: z.enum(["session", "profile"])
|
|
1260
1308
|
});
|
|
1309
|
+
var subaccountPinSchema = z.object({
|
|
1310
|
+
kind: z.string(),
|
|
1311
|
+
id: z.string(),
|
|
1312
|
+
name: z.string().optional()
|
|
1313
|
+
});
|
|
1261
1314
|
var authProfileSchema = z.object({
|
|
1262
1315
|
id: z.string(),
|
|
1263
1316
|
vendor: z.string(),
|
|
1264
1317
|
method: authMethodSchema,
|
|
1265
1318
|
credentialRef: z.string().optional(),
|
|
1266
1319
|
source: z.string().optional(),
|
|
1320
|
+
subaccount: subaccountPinSchema.optional(),
|
|
1267
1321
|
label: z.string().optional(),
|
|
1268
1322
|
// Additive, back-compat fields — an entry that predates them parses
|
|
1269
1323
|
// unchanged (both optional), and `endpoint` still shadows the on-disk
|
|
@@ -1310,12 +1364,13 @@ async function writeAuthProfiles(file) {
|
|
|
1310
1364
|
}
|
|
1311
1365
|
async function listAuthProfiles(endpoint) {
|
|
1312
1366
|
const file = await loadAuthProfiles();
|
|
1313
|
-
const all = Object.values(file.profiles);
|
|
1367
|
+
const all = Object.values(file.profiles).map(migrateLegacySubaccountProfile);
|
|
1314
1368
|
return endpoint === void 0 ? all : all.filter((p) => p.endpoint === endpoint);
|
|
1315
1369
|
}
|
|
1316
1370
|
async function getAuthProfile(id) {
|
|
1317
1371
|
const file = await loadAuthProfiles();
|
|
1318
|
-
|
|
1372
|
+
const profile = file.profiles[id];
|
|
1373
|
+
return profile ? migrateLegacySubaccountProfile(profile) : void 0;
|
|
1319
1374
|
}
|
|
1320
1375
|
async function addAuthProfile(profile) {
|
|
1321
1376
|
const file = await loadAuthProfiles();
|
|
@@ -1360,13 +1415,49 @@ function validateCreateInput(input) {
|
|
|
1360
1415
|
}
|
|
1361
1416
|
const credential = input.credential !== void 0 ? input.credential.trim() : void 0;
|
|
1362
1417
|
const source = input.source?.trim();
|
|
1363
|
-
|
|
1364
|
-
|
|
1418
|
+
let subaccount;
|
|
1419
|
+
if (input.subaccount !== void 0) {
|
|
1420
|
+
const kind = (input.subaccount.kind ?? "").trim();
|
|
1421
|
+
const subId = (input.subaccount.id ?? "").trim();
|
|
1422
|
+
const subName = input.subaccount.name?.trim();
|
|
1423
|
+
if (!SUBACCOUNT_KIND_RE.test(kind) || !subId) {
|
|
1365
1424
|
throw new AuthProfileValidationError(
|
|
1366
|
-
"
|
|
1425
|
+
`subaccount must be "<kind>:<id>" with a lowercase kind (org, workspace, project, \u2026) and a non-empty id`
|
|
1367
1426
|
);
|
|
1368
1427
|
}
|
|
1369
|
-
|
|
1428
|
+
subaccount = { kind, id: subId, ...subName ? { name: subName } : {} };
|
|
1429
|
+
if (!credential && !source) {
|
|
1430
|
+
throw new AuthProfileValidationError(
|
|
1431
|
+
"a subaccount pin needs a parent account \u2014 give a credential or a source"
|
|
1432
|
+
);
|
|
1433
|
+
}
|
|
1434
|
+
}
|
|
1435
|
+
const provider = source ? findSubaccountProvider({ source }) : void 0;
|
|
1436
|
+
if (subaccount && provider && !provider.kinds.includes(subaccount.kind)) {
|
|
1437
|
+
throw new AuthProfileValidationError(
|
|
1438
|
+
`subaccount kind "${subaccount.kind}" is not supported by "${provider.id}" (supported: ${provider.kinds.join(", ")})`
|
|
1439
|
+
);
|
|
1440
|
+
}
|
|
1441
|
+
if (method === "api-key") {
|
|
1442
|
+
if (source) {
|
|
1443
|
+
if (!provider) {
|
|
1444
|
+
throw new AuthProfileValidationError(
|
|
1445
|
+
`source is only supported for oauth-bearer profiles and for accounts owned by a registered sub-account provider \u2014 api-key profiles otherwise require a credential`
|
|
1446
|
+
);
|
|
1447
|
+
}
|
|
1448
|
+
if (!subaccount && provider.migrateLegacySource?.(source) === void 0) {
|
|
1449
|
+
throw new AuthProfileValidationError(
|
|
1450
|
+
`source "${source}" resolves an account with sub-accounts \u2014 pin one with a subaccount ("<kind>:<id>")`
|
|
1451
|
+
);
|
|
1452
|
+
}
|
|
1453
|
+
if (credential) {
|
|
1454
|
+
throw new AuthProfileValidationError(
|
|
1455
|
+
"give either credential or source, not both \u2014 a source-backed profile stores no secret"
|
|
1456
|
+
);
|
|
1457
|
+
}
|
|
1458
|
+
} else if (!credential) {
|
|
1459
|
+
throw new AuthProfileValidationError("credential is required");
|
|
1460
|
+
}
|
|
1370
1461
|
} else {
|
|
1371
1462
|
if (credential && source) {
|
|
1372
1463
|
throw new AuthProfileValidationError(
|
|
@@ -1391,6 +1482,7 @@ function validateCreateInput(input) {
|
|
|
1391
1482
|
method,
|
|
1392
1483
|
...credential ? { credential } : {},
|
|
1393
1484
|
...source ? { source } : {},
|
|
1485
|
+
...subaccount ? { subaccount } : {},
|
|
1394
1486
|
...label ? { label } : {},
|
|
1395
1487
|
...credentialRef ? { credentialRef } : {},
|
|
1396
1488
|
...origin ? { origin } : {}
|
|
@@ -1423,20 +1515,22 @@ async function createAuthProfile(input, deps) {
|
|
|
1423
1515
|
);
|
|
1424
1516
|
}
|
|
1425
1517
|
if (v.source !== void 0) {
|
|
1426
|
-
const profile2 = {
|
|
1518
|
+
const profile2 = migrateLegacySubaccountProfile({
|
|
1427
1519
|
id: v.id,
|
|
1428
1520
|
endpoint: v.endpoint,
|
|
1429
1521
|
method: v.method,
|
|
1430
1522
|
source: v.source,
|
|
1523
|
+
...v.subaccount ? { subaccount: v.subaccount } : {},
|
|
1431
1524
|
...v.label ? { label: v.label } : {},
|
|
1432
1525
|
...v.origin ? { origin: v.origin } : {}
|
|
1433
|
-
};
|
|
1526
|
+
});
|
|
1434
1527
|
await deps.addProfile(profile2);
|
|
1435
1528
|
return {
|
|
1436
1529
|
id: profile2.id,
|
|
1437
1530
|
endpoint: profile2.endpoint,
|
|
1438
1531
|
method: profile2.method,
|
|
1439
|
-
source:
|
|
1532
|
+
source: profile2.source,
|
|
1533
|
+
...profile2.subaccount ? { subaccount: profile2.subaccount } : {},
|
|
1440
1534
|
...profile2.label ? { label: profile2.label } : {},
|
|
1441
1535
|
...profile2.origin ? { origin: profile2.origin } : {}
|
|
1442
1536
|
};
|
|
@@ -1457,6 +1551,7 @@ async function createAuthProfile(input, deps) {
|
|
|
1457
1551
|
endpoint: v.endpoint,
|
|
1458
1552
|
method: v.method,
|
|
1459
1553
|
credentialRef,
|
|
1554
|
+
...v.subaccount ? { subaccount: v.subaccount } : {},
|
|
1460
1555
|
...v.label ? { label: v.label } : {},
|
|
1461
1556
|
...v.origin ? { origin: v.origin } : {}
|
|
1462
1557
|
};
|
|
@@ -1466,6 +1561,7 @@ async function createAuthProfile(input, deps) {
|
|
|
1466
1561
|
endpoint: profile.endpoint,
|
|
1467
1562
|
method: profile.method,
|
|
1468
1563
|
credentialRef,
|
|
1564
|
+
...v.subaccount ? { subaccount: v.subaccount } : {},
|
|
1469
1565
|
...profile.label ? { label: profile.label } : {},
|
|
1470
1566
|
...profile.origin ? { origin: profile.origin } : {},
|
|
1471
1567
|
fingerprint: fingerprintCredential(credential)
|
|
@@ -1626,6 +1722,6 @@ function eligibleProfiles(profiles, manifest, route) {
|
|
|
1626
1722
|
var SPEC_NAME = "agentauth";
|
|
1627
1723
|
var SPEC_VERSION = "v1";
|
|
1628
1724
|
|
|
1629
|
-
export { AuthProfileValidationError, BUILTIN_AUTH_PROVIDERS, CeremonyRequiredError, CredentialBroker, DiscoveryError, FLOW_ENGINES, FileStore, KeychainStore, MemoryStore, SPEC_NAME, SPEC_VERSION, addAuthProfile, authConfigSchema, authProfilesPath, authProviderFrontmatterSchema, createAuthProfile, credentialIdentity, defineAuthProvider, deleteAuthProfile, deleteKeychainToken, deriveCredentialRef, discoverEndpoints, eligibleProfiles, fingerprintCredential, getAuthProfile, getAuthProvider, guildeAuthProvider, installConfigSchema, listAuthProfiles, listAuthProviderIds, listAuthProviders, loadAuthProfiles, methodsPresentable, parseAuthProviderManifest, parseAuthProviderManifestRaw, readKeychainToken, refreshAuthProfileModels, registerAuthProvider, removeAuthProfile, resolveAccount, resolveEndpoint, resolveStoreRef, runAuthFlow, setAuthProfileEnabled, setAuthProfileModels, tokenStoreSpecSchema, updateAuthProfile, validateCreateInput, writeKeychainToken };
|
|
1725
|
+
export { AuthProfileValidationError, BUILTIN_AUTH_PROVIDERS, CeremonyRequiredError, CredentialBroker, DiscoveryError, FLOW_ENGINES, FileStore, KeychainStore, MemoryStore, SPEC_NAME, SPEC_VERSION, SUBACCOUNT_KIND_RE, SubaccountError, addAuthProfile, authConfigSchema, authProfilesPath, authProviderFrontmatterSchema, createAuthProfile, credentialIdentity, defineAuthProvider, deleteAuthProfile, deleteKeychainToken, deriveCredentialRef, discoverEndpoints, eligibleProfiles, findSubaccountProvider, fingerprintCredential, getAuthProfile, getAuthProvider, getSubaccountProvider, guildeAuthProvider, installConfigSchema, listAuthProfiles, listAuthProviderIds, listAuthProviders, listSubaccountProviders, loadAuthProfiles, methodsPresentable, migrateLegacySubaccountProfile, parseAuthProviderManifest, parseAuthProviderManifestRaw, parseSubaccountPin, readKeychainToken, refreshAuthProfileModels, registerAuthProvider, registerSubaccountProvider, removeAuthProfile, resolveAccount, resolveEndpoint, resolveStoreRef, runAuthFlow, setAuthProfileEnabled, setAuthProfileModels, tokenStoreSpecSchema, unregisterSubaccountProvider, updateAuthProfile, validateCreateInput, writeKeychainToken };
|
|
1630
1726
|
//# sourceMappingURL=index.mjs.map
|
|
1631
1727
|
//# sourceMappingURL=index.mjs.map
|