@agentproto/auth 0.2.0 → 1.0.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 +2 -1
- package/dist/index.d.ts +325 -31
- package/dist/index.mjs +255 -14
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ Aligned to the WorkOS [auth.md](https://github.com/workos/auth.md) open standard
|
|
|
10
10
|
two-hop `.well-known` discovery, the `agent_auth` metadata block, and the
|
|
11
11
|
service-auth claim ceremony (`urn:workos:agent-auth:grant-type:claim`).
|
|
12
12
|
|
|
13
|
-
> **Status: 0.
|
|
13
|
+
> **Status: 0.2.0-alpha.** Two flows specified in v1 (`pat`, `service-auth`);
|
|
14
14
|
> `id-jag` (agentproto-as-IdP) is reserved.
|
|
15
15
|
|
|
16
16
|
Spec: <https://agentproto.sh/docs/aip-50> · Standard: <https://github.com/workos/auth.md>
|
|
@@ -240,6 +240,7 @@ through that structural seam. See `@agentproto/secrets`' README.
|
|
|
240
240
|
| `runAuthFlow` | resolve → discover → dispatch |
|
|
241
241
|
| `FLOW_ENGINES` | registered flow engines (`pat`, `service-auth`) |
|
|
242
242
|
| `CredentialBroker` / `CredentialBrokerOptions` | path → fresh `resolveHeaders` |
|
|
243
|
+
| `eligibleProfiles` | `(adapter × route) → vendor + profile eligibility predicate` |
|
|
243
244
|
| `CredentialStore` / `StoreRef` / `StoredCredential` | pluggable-store interface + shapes |
|
|
244
245
|
| `KeychainStore` / `MemoryStore` / `FileStore` / `resolveStoreRef` | built-in backends + ref resolver |
|
|
245
246
|
| `readKeychainToken` / `writeKeychainToken` / `resolveAccount` | Keychain helpers |
|
package/dist/index.d.ts
CHANGED
|
@@ -443,6 +443,10 @@ declare function resolveAccount(account: string | undefined, server: string): st
|
|
|
443
443
|
declare function readKeychainToken(service: string, account: string): Promise<string | undefined>;
|
|
444
444
|
/** Write a token to the Keychain (-U updates in place). */
|
|
445
445
|
declare function writeKeychainToken(service: string, account: string, token: string): Promise<void>;
|
|
446
|
+
/** Remove a token from the Keychain. Returns true if an entry was deleted,
|
|
447
|
+
* false when none existed (a delete of an absent entry is not an error —
|
|
448
|
+
* the desired end state, "no credential at this slot", already holds). */
|
|
449
|
+
declare function deleteKeychainToken(service: string, account: string): Promise<boolean>;
|
|
446
450
|
|
|
447
451
|
/**
|
|
448
452
|
* KeychainStore — `CredentialStore` backed by the platform Keychain.
|
|
@@ -460,6 +464,7 @@ declare function writeKeychainToken(service: string, account: string, token: str
|
|
|
460
464
|
declare class KeychainStore implements CredentialStore {
|
|
461
465
|
read(ref: StoreRef): Promise<StoredCredential | undefined>;
|
|
462
466
|
write(ref: StoreRef, cred: StoredCredential): Promise<void>;
|
|
467
|
+
delete(ref: StoreRef): Promise<void>;
|
|
463
468
|
}
|
|
464
469
|
|
|
465
470
|
/**
|
|
@@ -543,10 +548,10 @@ declare class CredentialBroker {
|
|
|
543
548
|
/**
|
|
544
549
|
* Named auth-profile types (SPEC §1c/§3.1 — `agentproto-session-config-axes`).
|
|
545
550
|
*
|
|
546
|
-
* A profile is a named credential `{
|
|
551
|
+
* A profile is a named credential `{ endpoint, method, credentialRef }` that
|
|
547
552
|
* lives independently of any adapter, generalizing `providers-store`'s
|
|
548
553
|
* `ProviderEntry` (one api-key per provider, `packages/providers-store/src/
|
|
549
|
-
* index.ts:68-80`) to N named profiles per
|
|
554
|
+
* index.ts:68-80`) to N named profiles per billing endpoint. `subscription|api-key` is
|
|
550
555
|
* not a session property — it demotes to the `method` facet of a profile.
|
|
551
556
|
*
|
|
552
557
|
* The secret itself is NEVER inlined here — `credentialRef` is an opaque
|
|
@@ -560,31 +565,103 @@ declare class CredentialBroker {
|
|
|
560
565
|
* (`types.ts:151`): `pat` → `api-key`, `oat` → `oauth-bearer`. Extensible —
|
|
561
566
|
* new methods are additive. */
|
|
562
567
|
type AuthMethod = "oauth-bearer" | "api-key";
|
|
563
|
-
/**
|
|
568
|
+
/** Per-profile model curation (the allowlist). `mode: "all"` (or an ABSENT
|
|
569
|
+
* {@link AuthProfile.models}) services every model the profile is otherwise
|
|
570
|
+
* eligible for — today's behavior. `mode: "allow"` narrows the profile to
|
|
571
|
+
* exactly `ids`: it services a model only when the model's catalog identity
|
|
572
|
+
* (its `vendor/product` or its route-qualified `ref`) is in the list. The
|
|
573
|
+
* intersection is applied INSIDE the catalog eligibility join
|
|
574
|
+
* (`catalog-models.ts`), never at the endpoint/method predicate here, so a
|
|
575
|
+
* curated profile stays endpoint-eligible but only makes its chosen model
|
|
576
|
+
* refs runnable. */
|
|
577
|
+
interface ModelCuration {
|
|
578
|
+
mode: "all" | "allow";
|
|
579
|
+
/** Model identities allowed when `mode === "allow"` — each a catalog
|
|
580
|
+
* `vendor/product` or route-qualified `ref`. Empty ⇒ services nothing. */
|
|
581
|
+
ids: string[];
|
|
582
|
+
}
|
|
583
|
+
/** Which spend surface a {@link CostBudget} caps. `"session"` bounds the
|
|
584
|
+
* windowed spend of the ONE session the budget is evaluated against;
|
|
585
|
+
* `"profile"` bounds the aggregate windowed spend of every session that
|
|
586
|
+
* resolved to the same auth profile (the session's `accessProfile.profileRef`).
|
|
587
|
+
* Additive — new scopes are back-compat. */
|
|
588
|
+
type CostBudgetScope = "session" | "profile";
|
|
589
|
+
/** A windowed spend cap. DISTINCT from the scalar `maxCostUsd` session-kill
|
|
590
|
+
* (`sessions.ts` turn-end) — a `CostBudget` never kills a session; it trips a
|
|
591
|
+
* governance policy (`policy:failed` on the completion-policy bus) when the
|
|
592
|
+
* ROLLING windowed spend for its {@link scope} crosses `maxCostUsd`. `window`
|
|
593
|
+
* is a rolling spec (`parseWindow` shorthand `"5h"`/`"7d"` or ISO-8601 `"P7D"`);
|
|
594
|
+
* spend is the priced local-estimate rollup over durable usage snapshots. */
|
|
595
|
+
interface CostBudget {
|
|
596
|
+
/** Windowed spend ceiling in USD. The budget trips when the window's priced
|
|
597
|
+
* spend strictly exceeds this. */
|
|
598
|
+
maxCostUsd: number;
|
|
599
|
+
/** Rolling window spec — `parseWindow`-parseable (`"5h"`, `"7d"`, `"P7D"`). */
|
|
600
|
+
window: string;
|
|
601
|
+
/** Which spend surface the window is summed over. See {@link CostBudgetScope}. */
|
|
602
|
+
scope: CostBudgetScope;
|
|
603
|
+
}
|
|
604
|
+
/** A named, billing-endpoint-scoped credential reference. */
|
|
564
605
|
interface AuthProfile {
|
|
565
606
|
/** Stable id, unique across all profiles (the `profileRef` a session
|
|
566
607
|
* attaches). */
|
|
567
608
|
id: string;
|
|
568
|
-
/** Which
|
|
569
|
-
*
|
|
609
|
+
/** Which billing endpoint this credential authenticates against
|
|
610
|
+
* (`anthropic`, `openrouter`, `moonshot`, …). This deliberately does NOT
|
|
611
|
+
* mean the model builder: OpenRouter can serve a z-ai model, for example.
|
|
612
|
+
* Kept as `string` here to stay decoupled from
|
|
570
613
|
* `@agentproto/model-catalog`, same rationale as the driver's
|
|
571
614
|
* `AgentCliDefinition.provider`. */
|
|
572
|
-
|
|
615
|
+
endpoint: string;
|
|
573
616
|
/** How this profile authenticates. */
|
|
574
617
|
method: AuthMethod;
|
|
575
618
|
/** Opaque handle into this package's credential storage — NEVER the secret
|
|
576
619
|
* itself. Resolved through `CredentialStore` / `token-store.ts` at use
|
|
577
|
-
* time, not stored inline.
|
|
578
|
-
|
|
620
|
+
* time, not stored inline. Set for a credential-backed profile; absent for
|
|
621
|
+
* a source-backed profile. Mutually exclusive with {@link source}. */
|
|
622
|
+
credentialRef?: string;
|
|
623
|
+
/** Self-refreshing credential source (`oauth-bearer` only) — same value
|
|
624
|
+
* spawn's subscription resolution accepts (today, only
|
|
625
|
+
* `"claude-code-oauth"`, `spawn-defaults.ts`'s `CLAUDE_CODE_OAUTH_SOURCE`).
|
|
626
|
+
* A source-backed profile has no stored secret: the credential is resolved
|
|
627
|
+
* fresh at spawn time instead. Mutually exclusive with
|
|
628
|
+
* {@link credentialRef}. */
|
|
629
|
+
source?: string;
|
|
579
630
|
/** Optional human-readable name ("Jeremy Max", "work OpenRouter"). */
|
|
580
631
|
label?: string;
|
|
632
|
+
/** Whole-profile enable/disable. ABSENT (or `false`) ⇒ enabled (today's
|
|
633
|
+
* behavior). `true` ⇒ the profile is skipped by {@link eligibleProfiles}
|
|
634
|
+
* entirely, so every model it would otherwise service drops to
|
|
635
|
+
* non-runnable. A REAL persisted state, distinct from the derived
|
|
636
|
+
* `runnable` flag the catalog computes. */
|
|
637
|
+
disabled?: boolean;
|
|
638
|
+
/** Optional per-model curation (the allowlist). ABSENT ⇒ `{ mode: "all" }`
|
|
639
|
+
* — services every eligible model, byte-identical to a profile that
|
|
640
|
+
* predates this field. See {@link ModelCuration}. */
|
|
641
|
+
models?: ModelCuration;
|
|
642
|
+
/** Optional windowed spend cap attached to this profile (SPEC §1c). ABSENT ⇒
|
|
643
|
+
* no profile-level budget — byte-identical to a profile that predates this
|
|
644
|
+
* field. When present with `scope: "profile"`, a governance policy evaluates
|
|
645
|
+
* the aggregate windowed spend of every session on this profile at each
|
|
646
|
+
* turn-end and trips `policy:failed` on overage. Distinct from the scalar
|
|
647
|
+
* session-kill `maxCostUsd` — see {@link CostBudget}. */
|
|
648
|
+
costBudget?: CostBudget;
|
|
649
|
+
/** Provenance: where this profile's credential was IMPORTED from, when it
|
|
650
|
+
* was materialized by the WS6 discovery→import flow
|
|
651
|
+
* (`auth_profile_import`) rather than created by hand. One of the discovery
|
|
652
|
+
* origins (`claude-code`, `hermes-config`, `env`, `codex`, `gemini`). Purely
|
|
653
|
+
* informational — it drives the panel's "imported from <origin>" badge and
|
|
654
|
+
* nothing in the spawn/eligibility path. ABSENT for a hand-created profile.
|
|
655
|
+
* Kept as `string` (not a union) to stay decoupled, same rationale as
|
|
656
|
+
* {@link endpoint}. */
|
|
657
|
+
origin?: string;
|
|
581
658
|
}
|
|
582
659
|
|
|
583
660
|
/**
|
|
584
661
|
* Named auth-profile store — CRUD over `~/.agentproto/auth-profiles.json`
|
|
585
662
|
* (mode 0600), generalizing `providers-store`'s single-key-per-provider file
|
|
586
663
|
* (`packages/providers-store/src/index.ts:68-90`, `ProviderEntry`/
|
|
587
|
-
* `ProvidersFile`) to N named `AuthProfile`s per
|
|
664
|
+
* `ProvidersFile`) to N named `AuthProfile`s per billing endpoint, keyed by `id`.
|
|
588
665
|
*
|
|
589
666
|
* This is the profile-metadata store, not the credential store: entries hold
|
|
590
667
|
* `credentialRef` (a pointer), never a secret, so — unlike `FileStore`
|
|
@@ -598,22 +675,58 @@ interface AuthProfile {
|
|
|
598
675
|
|
|
599
676
|
declare const authProfilesFileSchema: z.ZodObject<{
|
|
600
677
|
version: z.ZodLiteral<1>;
|
|
601
|
-
profiles: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
678
|
+
profiles: z.ZodRecord<z.ZodString, z.ZodPipe<z.ZodObject<{
|
|
602
679
|
id: z.ZodString;
|
|
603
680
|
vendor: z.ZodString;
|
|
604
681
|
method: z.ZodEnum<{
|
|
605
682
|
"oauth-bearer": "oauth-bearer";
|
|
606
683
|
"api-key": "api-key";
|
|
607
684
|
}>;
|
|
608
|
-
credentialRef: z.ZodString
|
|
685
|
+
credentialRef: z.ZodOptional<z.ZodString>;
|
|
686
|
+
source: z.ZodOptional<z.ZodString>;
|
|
609
687
|
label: z.ZodOptional<z.ZodString>;
|
|
610
|
-
|
|
688
|
+
disabled: z.ZodOptional<z.ZodBoolean>;
|
|
689
|
+
models: z.ZodOptional<z.ZodObject<{
|
|
690
|
+
mode: z.ZodEnum<{
|
|
691
|
+
allow: "allow";
|
|
692
|
+
all: "all";
|
|
693
|
+
}>;
|
|
694
|
+
ids: z.ZodArray<z.ZodString>;
|
|
695
|
+
}, z.core.$strip>>;
|
|
696
|
+
costBudget: z.ZodOptional<z.ZodObject<{
|
|
697
|
+
maxCostUsd: z.ZodNumber;
|
|
698
|
+
window: z.ZodString;
|
|
699
|
+
scope: z.ZodEnum<{
|
|
700
|
+
session: "session";
|
|
701
|
+
profile: "profile";
|
|
702
|
+
}>;
|
|
703
|
+
}, z.core.$strip>>;
|
|
704
|
+
origin: z.ZodOptional<z.ZodString>;
|
|
705
|
+
}, z.core.$strip>, z.ZodTransform<AuthProfile, {
|
|
706
|
+
id: string;
|
|
707
|
+
vendor: string;
|
|
708
|
+
method: "oauth-bearer" | "api-key";
|
|
709
|
+
credentialRef?: string | undefined;
|
|
710
|
+
source?: string | undefined;
|
|
711
|
+
label?: string | undefined;
|
|
712
|
+
disabled?: boolean | undefined;
|
|
713
|
+
models?: {
|
|
714
|
+
mode: "allow" | "all";
|
|
715
|
+
ids: string[];
|
|
716
|
+
} | undefined;
|
|
717
|
+
costBudget?: {
|
|
718
|
+
maxCostUsd: number;
|
|
719
|
+
window: string;
|
|
720
|
+
scope: "session" | "profile";
|
|
721
|
+
} | undefined;
|
|
722
|
+
origin?: string | undefined;
|
|
723
|
+
}>>>;
|
|
611
724
|
}, z.core.$strip>;
|
|
612
725
|
type AuthProfilesFile = z.infer<typeof authProfilesFileSchema>;
|
|
613
726
|
declare function authProfilesPath(): string;
|
|
614
727
|
declare function loadAuthProfiles(): Promise<AuthProfilesFile>;
|
|
615
|
-
/** List all profiles, optionally filtered to one
|
|
616
|
-
declare function listAuthProfiles(
|
|
728
|
+
/** List all profiles, optionally filtered to one billing endpoint. */
|
|
729
|
+
declare function listAuthProfiles(endpoint?: string): Promise<AuthProfile[]>;
|
|
617
730
|
/** Look up a single profile by id, or undefined if none exists. */
|
|
618
731
|
declare function getAuthProfile(id: string): Promise<AuthProfile | undefined>;
|
|
619
732
|
/** Add (or replace) a profile, keyed by its `id`. */
|
|
@@ -622,16 +735,194 @@ declare function addAuthProfile(profile: AuthProfile): Promise<void>;
|
|
|
622
735
|
declare function removeAuthProfile(id: string): Promise<boolean>;
|
|
623
736
|
|
|
624
737
|
/**
|
|
625
|
-
*
|
|
738
|
+
* Auth-profile provisioning — the create/delete flow the store CRUD
|
|
739
|
+
* (`profile-store.ts`) deliberately leaves out.
|
|
740
|
+
*
|
|
741
|
+
* `profile-store.ts` writes only profile *metadata* (`credentialRef`, a
|
|
742
|
+
* pointer). Provisioning is the two-sided operation nobody else owned: write
|
|
743
|
+
* the *secret* to the credential store at a derived slot, THEN record the
|
|
744
|
+
* metadata pointing at it — and, on delete, tear both down together. This is
|
|
745
|
+
* the single place that knows the `agentproto.auth.<vendor>[.<qualifier>]`
|
|
746
|
+
* keychain-slot convention (matching the entries seeded by hand in
|
|
747
|
+
* `~/.agentproto/auth-profiles.json`).
|
|
748
|
+
*
|
|
749
|
+
* The secret is INPUT-only. It is written to the `CredentialStore` and never
|
|
750
|
+
* echoed back: `createAuthProfile` returns non-secret metadata plus a
|
|
751
|
+
* one-way `fingerprint` (same "fingerprint, don't echo" discipline as
|
|
752
|
+
* `broker.ts` / `KeychainStore`), so a caller can confirm *which* credential
|
|
753
|
+
* landed without ever seeing it.
|
|
754
|
+
*
|
|
755
|
+
* Dependency-injected (`ProfileProvisionDeps`) so it's unit-testable against
|
|
756
|
+
* a `MemoryStore` + an in-memory profile map, with no keychain or filesystem.
|
|
757
|
+
*/
|
|
758
|
+
|
|
759
|
+
/** Input to {@link createAuthProfile}. `credential` is the raw secret — it is
|
|
760
|
+
* written to the store and NEVER returned. Exactly one of `credential` /
|
|
761
|
+
* `source` must be given for an `oauth-bearer` profile; `api-key` always
|
|
762
|
+
* requires `credential` (a source-backed profile only makes sense for a
|
|
763
|
+
* self-refreshing subscription bearer). */
|
|
764
|
+
interface CreateAuthProfileInput {
|
|
765
|
+
/** Stable id, unique across all profiles. */
|
|
766
|
+
id: string;
|
|
767
|
+
/** Billing endpoint / vendor this credential authenticates against
|
|
768
|
+
* (`anthropic`, `openrouter`, `moonshot`, …). */
|
|
769
|
+
endpoint: string;
|
|
770
|
+
/** How this profile authenticates. */
|
|
771
|
+
method: AuthMethod;
|
|
772
|
+
/** The raw secret (a subscription OAuth bearer, an API key). INPUT-ONLY.
|
|
773
|
+
* Mutually exclusive with `source`. */
|
|
774
|
+
credential?: string;
|
|
775
|
+
/** Self-refreshing credential source (`oauth-bearer` only, e.g.
|
|
776
|
+
* `"claude-code-oauth"`) — the profile stores no secret; the credential is
|
|
777
|
+
* resolved fresh at spawn time instead. Mutually exclusive with
|
|
778
|
+
* `credential`. */
|
|
779
|
+
source?: string;
|
|
780
|
+
/** Optional human-readable name. */
|
|
781
|
+
label?: string;
|
|
782
|
+
/** Optional explicit credential-store slot. Omitted ⇒ derived from
|
|
783
|
+
* `endpoint` + `method` (see {@link deriveCredentialRef}). Ignored for a
|
|
784
|
+
* source-backed profile (nothing is written to the credential store). */
|
|
785
|
+
credentialRef?: string;
|
|
786
|
+
/** Optional provenance — where the credential was imported from (a WS6
|
|
787
|
+
* discovery origin). Stamped verbatim on the created profile; purely
|
|
788
|
+
* informational. */
|
|
789
|
+
origin?: string;
|
|
790
|
+
}
|
|
791
|
+
/** The non-secret result of a create — safe to log, return over the wire, or
|
|
792
|
+
* render in a UI. Carries a fingerprint, never the credential. */
|
|
793
|
+
interface CreatedAuthProfile {
|
|
794
|
+
id: string;
|
|
795
|
+
endpoint: string;
|
|
796
|
+
method: AuthMethod;
|
|
797
|
+
/** Set for a credential-backed profile; absent for a source-backed one. */
|
|
798
|
+
credentialRef?: string;
|
|
799
|
+
/** Set for a source-backed profile; absent for a credential-backed one. */
|
|
800
|
+
source?: string;
|
|
801
|
+
label?: string;
|
|
802
|
+
/** Provenance stamped at import time, when given. */
|
|
803
|
+
origin?: string;
|
|
804
|
+
/** One-way fingerprint of the stored credential (sha256, truncated) — lets
|
|
805
|
+
* a caller confirm *which* secret was stored without exposing it. Absent
|
|
806
|
+
* for a source-backed profile — there is no stored secret to fingerprint. */
|
|
807
|
+
fingerprint?: string;
|
|
808
|
+
}
|
|
809
|
+
/** The result of a delete. `deleted` is false when no profile had that id
|
|
810
|
+
* (idempotent — the desired end state already held). */
|
|
811
|
+
interface DeletedAuthProfile {
|
|
812
|
+
deleted: boolean;
|
|
813
|
+
id: string;
|
|
814
|
+
/** The slot the credential lived at, when a profile was actually removed. */
|
|
815
|
+
credentialRef?: string;
|
|
816
|
+
}
|
|
817
|
+
/** Injectable persistence surface — production wires these to
|
|
818
|
+
* `profile-store.ts` + a `KeychainStore`; tests pass in-memory doubles. */
|
|
819
|
+
interface ProfileProvisionDeps {
|
|
820
|
+
/** Where secrets live (a `KeychainStore` in production). */
|
|
821
|
+
store: CredentialStore;
|
|
822
|
+
getProfile: (id: string) => Promise<AuthProfile | undefined>;
|
|
823
|
+
listProfiles: () => Promise<AuthProfile[]>;
|
|
824
|
+
addProfile: (profile: AuthProfile) => Promise<void>;
|
|
825
|
+
removeProfile: (id: string) => Promise<boolean>;
|
|
826
|
+
}
|
|
827
|
+
/** Raised when create/delete input fails validation. Distinct type so a host
|
|
828
|
+
* (HTTP route, MCP tool) can map it to a 400 rather than a 500. */
|
|
829
|
+
declare class AuthProfileValidationError extends Error {
|
|
830
|
+
constructor(message: string);
|
|
831
|
+
}
|
|
832
|
+
/** Normalized, validated create input — every field trimmed and checked.
|
|
833
|
+
* Exactly one of `credential` / `source` is present. */
|
|
834
|
+
interface ValidatedCreateInput {
|
|
835
|
+
id: string;
|
|
836
|
+
endpoint: string;
|
|
837
|
+
method: AuthMethod;
|
|
838
|
+
credential?: string;
|
|
839
|
+
source?: string;
|
|
840
|
+
label?: string;
|
|
841
|
+
credentialRef?: string;
|
|
842
|
+
origin?: string;
|
|
843
|
+
}
|
|
844
|
+
/**
|
|
845
|
+
* Validate + normalize raw create input. Pure — no I/O. Throws
|
|
846
|
+
* {@link AuthProfileValidationError} with a specific message on the first
|
|
847
|
+
* problem it finds, so the surface layer can surface a clear 400.
|
|
848
|
+
*/
|
|
849
|
+
declare function validateCreateInput(input: CreateAuthProfileInput): ValidatedCreateInput;
|
|
850
|
+
/**
|
|
851
|
+
* Derive the credential-store slot for a profile. Matches the convention of
|
|
852
|
+
* the hand-seeded entries: `agentproto.auth.<endpoint>` for an api-key,
|
|
853
|
+
* `agentproto.auth.<endpoint>.sub` for a subscription (oauth-bearer), plus an
|
|
854
|
+
* optional `<qualifier>` to disambiguate a second profile on the same
|
|
855
|
+
* endpoint+method. Pure.
|
|
856
|
+
*/
|
|
857
|
+
declare function deriveCredentialRef(input: {
|
|
858
|
+
endpoint: string;
|
|
859
|
+
method: AuthMethod;
|
|
860
|
+
qualifier?: string;
|
|
861
|
+
}): string;
|
|
862
|
+
/** One-way fingerprint of a secret — sha256, first 12 hex chars. Enough to
|
|
863
|
+
* distinguish credentials by eye; not reversible. */
|
|
864
|
+
declare function fingerprintCredential(secret: string): string;
|
|
865
|
+
/** Non-secret identity of a STORED credential — a one-way {@link
|
|
866
|
+
* fingerprintCredential} plus the trailing 4 characters (the standard
|
|
867
|
+
* "which key is this" affordance, like a card's last four). Neither is
|
|
868
|
+
* reversible to the secret. `last4` is omitted for a secret too short to
|
|
869
|
+
* reveal a tail safely (see {@link MIN_LEN_FOR_LAST4}) — fail closed rather
|
|
870
|
+
* than expose. */
|
|
871
|
+
interface CredentialIdentity {
|
|
872
|
+
fingerprint: string;
|
|
873
|
+
last4?: string;
|
|
874
|
+
}
|
|
875
|
+
/** Compute the non-secret {@link CredentialIdentity} of a stored secret.
|
|
876
|
+
* Money-safety: returns ONLY the one-way fingerprint + a trailing tail —
|
|
877
|
+
* never the secret, and never the tail when the secret is too short to
|
|
878
|
+
* reveal one safely. */
|
|
879
|
+
declare function credentialIdentity(secret: string): CredentialIdentity;
|
|
880
|
+
/**
|
|
881
|
+
* Create a profile end-to-end: validate, derive the credential slot (avoiding
|
|
882
|
+
* collision with an existing profile's slot), write the secret to the store,
|
|
883
|
+
* then record the metadata. Rejects a duplicate id rather than silently
|
|
884
|
+
* overwriting. Returns non-secret metadata + a fingerprint; the credential is
|
|
885
|
+
* never echoed back.
|
|
886
|
+
*/
|
|
887
|
+
declare function createAuthProfile(input: CreateAuthProfileInput, deps: ProfileProvisionDeps): Promise<CreatedAuthProfile>;
|
|
888
|
+
/**
|
|
889
|
+
* Delete a profile and its credential. Idempotent: a missing id returns
|
|
890
|
+
* `{ deleted: false }` rather than throwing. The keychain entry is removed
|
|
891
|
+
* only when no OTHER profile still references the same slot — two profiles
|
|
892
|
+
* can legitimately share a `credentialRef`, and dropping one must not strand
|
|
893
|
+
* the other.
|
|
894
|
+
*/
|
|
895
|
+
declare function deleteAuthProfile(id: string, deps: ProfileProvisionDeps): Promise<DeletedAuthProfile>;
|
|
896
|
+
/**
|
|
897
|
+
* Enable or disable a whole profile (WS2). Metadata-only — never touches the
|
|
898
|
+
* credential store. Enabling CLEARS the `disabled` field entirely rather than
|
|
899
|
+
* writing `disabled: false`, so a re-enabled profile is byte-identical on
|
|
900
|
+
* disk to one that was never disabled (the ABSENT-means-enabled invariant).
|
|
901
|
+
* Throws {@link AuthProfileValidationError} for an unknown id so a host can map
|
|
902
|
+
* it to a 404/400. Returns the updated (non-secret) profile.
|
|
903
|
+
*/
|
|
904
|
+
declare function setAuthProfileEnabled(id: string, enabled: boolean, deps: ProfileProvisionDeps): Promise<AuthProfile>;
|
|
905
|
+
/**
|
|
906
|
+
* Set a profile's per-model curation allowlist (WS3). Metadata-only. `mode:
|
|
907
|
+
* "all"` CLEARS the `models` field entirely (curation off ⇒ absent, the
|
|
908
|
+
* byte-identical "services everything" default), so only a genuine `mode:
|
|
909
|
+
* "allow"` persists a `models` object. `ids` are trimmed, de-duped, and
|
|
910
|
+
* blanks dropped. Throws {@link AuthProfileValidationError} for an unknown id.
|
|
911
|
+
* Returns the updated (non-secret) profile.
|
|
912
|
+
*/
|
|
913
|
+
declare function setAuthProfileModels(id: string, curation: ModelCuration, deps: ProfileProvisionDeps): Promise<AuthProfile>;
|
|
914
|
+
|
|
915
|
+
/**
|
|
916
|
+
* (adapter × route) → billing-endpoint resolution + the profile eligibility predicate
|
|
626
917
|
* (SPEC §1c, `agentproto-session-config-axes/SPEC.md:102-125`).
|
|
627
918
|
*
|
|
628
919
|
* profile eligible for (adapter, route) iff
|
|
629
|
-
* profile.
|
|
920
|
+
* profile.endpoint == resolveEndpoint(adapter, route).endpoint
|
|
630
921
|
* AND profile.method ∈ methodsPresentable(adapter, route)
|
|
631
922
|
*
|
|
632
923
|
* `route` is the endpoint selector (SPEC axis #4 — direct vs a gateway mode
|
|
633
924
|
* like `moonshot`/`openrouter`), so access is deliberately downstream of it:
|
|
634
|
-
* which
|
|
925
|
+
* which endpoint (and thus which profiles) are eligible changes when route
|
|
635
926
|
* changes. `AdapterAuthManifest` is a narrow, package-local projection of
|
|
636
927
|
* exactly what this predicate needs from an adapter's real AIP-45 manifest
|
|
637
928
|
* (`packages/driver/agent-cli/src/types.ts`'s `AgentCliDefinition`) — this
|
|
@@ -640,7 +931,7 @@ declare function removeAuthProfile(id: string): Promise<boolean>;
|
|
|
640
931
|
* runtime is the one that will later project a real manifest into this
|
|
641
932
|
* shape (out of scope here — foundation only, no live spawn-path wiring).
|
|
642
933
|
*
|
|
643
|
-
* `methodsByRoute` is the static per-
|
|
934
|
+
* `methodsByRoute` is the static per-endpoint method table ADR'd in SPEC §3.4:
|
|
644
935
|
* "which auth methods this adapter can present for a resolved route." It is
|
|
645
936
|
* the derivable replacement for two hand-maintained artifacts SPEC §1c calls
|
|
646
937
|
* out for eventual removal — the per-adapter `authSubscription` boolean
|
|
@@ -655,33 +946,36 @@ declare function removeAuthProfile(id: string): Promise<boolean>;
|
|
|
655
946
|
*/
|
|
656
947
|
|
|
657
948
|
/** A narrow, package-local projection of an adapter's declared auth
|
|
658
|
-
* capability — enough to resolve (adapter, route) →
|
|
949
|
+
* capability — enough to resolve (adapter, route) → endpoint and the auth
|
|
659
950
|
* methods presentable on that route. Not the real AIP-45 manifest type. */
|
|
660
951
|
interface AdapterAuthManifest {
|
|
661
952
|
/** Adapter id (e.g. "claude-code", "hermes"), for error messages only. */
|
|
662
953
|
id: string;
|
|
663
954
|
/** route id (e.g. "direct", or a gateway mode id like "moonshot") →
|
|
664
|
-
* the
|
|
665
|
-
|
|
955
|
+
* the billing endpoint used when spawned on that route. */
|
|
956
|
+
endpointByRoute: Readonly<Record<string, string>>;
|
|
666
957
|
/** route id → the auth methods this adapter can present when spawned on
|
|
667
958
|
* that route — the method-side of the eligibility predicate. */
|
|
668
959
|
methodsByRoute: Readonly<Record<string, readonly AuthMethod[]>>;
|
|
669
960
|
}
|
|
670
|
-
/** Resolve which
|
|
671
|
-
* when the manifest declares no
|
|
961
|
+
/** Resolve which billing endpoint a given (adapter, route) pair uses. Throws
|
|
962
|
+
* when the manifest declares no endpoint for `route` — an unresolvable route
|
|
672
963
|
* is a caller bug (a bad/unknown route id), not a "no profiles eligible"
|
|
673
|
-
* case, so this fails loud rather than returning an empty
|
|
964
|
+
* case, so this fails loud rather than returning an empty endpoint. */
|
|
674
965
|
declare function resolveEndpoint(manifest: AdapterAuthManifest, route: string): {
|
|
675
|
-
|
|
966
|
+
endpoint: string;
|
|
676
967
|
};
|
|
677
968
|
/** Which auth methods `manifest`'s adapter can present on `route`. Empty
|
|
678
969
|
* (never throws) when the route is declared for vendor resolution but has
|
|
679
970
|
* no methods table entry — that's "no eligible profiles", a legitimate
|
|
680
971
|
* eligibility outcome, not an error. */
|
|
681
972
|
declare function methodsPresentable(manifest: AdapterAuthManifest, route: string): AuthMethod[];
|
|
682
|
-
/** The eligibility predicate: profiles whose
|
|
683
|
-
* resolved endpoint AND whose method the adapter can present on that
|
|
684
|
-
*
|
|
973
|
+
/** The eligibility predicate: profiles whose endpoint matches the route's
|
|
974
|
+
* resolved endpoint AND whose method the adapter can present on that route.
|
|
975
|
+
* A whole-profile-disabled profile (`disabled: true`) is skipped outright —
|
|
976
|
+
* every model it would otherwise service drops to non-runnable (WS2). This is
|
|
977
|
+
* the profile-level gate; per-model curation (`models`) is intersected
|
|
978
|
+
* downstream in the catalog join, not here (SPEC §1c / catalog-models.ts). */
|
|
685
979
|
declare function eligibleProfiles(profiles: readonly AuthProfile[], manifest: AdapterAuthManifest, route: string): AuthProfile[];
|
|
686
980
|
|
|
687
981
|
/** Guilde AI company platform.
|
|
@@ -714,15 +1008,15 @@ declare const BUILTIN_AUTH_PROVIDERS: readonly AuthProviderHandle[];
|
|
|
714
1008
|
* KeychainStore / MemoryStore / FileStore — built-in CredentialStore backends
|
|
715
1009
|
* resolveStoreRef(spec, server) — map a TokenStoreSpec to a StoreRef
|
|
716
1010
|
* CredentialBroker — path → ready-to-use auth headers
|
|
717
|
-
* AuthProfile / AuthMethod — named,
|
|
1011
|
+
* AuthProfile / AuthMethod — named, endpoint-scoped credential ref
|
|
718
1012
|
* listAuthProfiles/getAuthProfile/
|
|
719
1013
|
* addAuthProfile/removeAuthProfile — named-profile store CRUD
|
|
720
1014
|
* resolveEndpoint/methodsPresentable/
|
|
721
|
-
* eligibleProfiles — (adapter × route) →
|
|
1015
|
+
* eligibleProfiles — (adapter × route) → endpoint + the
|
|
722
1016
|
* profile eligibility predicate
|
|
723
1017
|
*/
|
|
724
1018
|
|
|
725
1019
|
declare const SPEC_NAME = "agentauth";
|
|
726
1020
|
declare const SPEC_VERSION = "v1";
|
|
727
1021
|
|
|
728
|
-
export { type AdapterAuthManifest, type AuthConfig, type AuthMethod, type AuthProfile, type AuthProfilesFile, type AuthProviderDefinition, type AuthProviderFrontmatter, type AuthProviderHandle, type AuthProviderManifest, BUILTIN_AUTH_PROVIDERS, CeremonyRequiredError, CredentialBroker, type CredentialBrokerOptions, type CredentialStore, type DeviceCodeAuthConfig, type DiscoveredEndpoints, DiscoveryError, FLOW_ENGINES, FileStore, type FlowEngine, type FlowId, type FlowResult, type FlowRunOptions, type InstallConfig, KeychainStore, MemoryStore, type PATAuthConfig, type RunFlowOptions, SPEC_NAME, SPEC_VERSION, type ServiceAuthConfig, type StoreRef, type StoredCredential, type TokenStoreSpec, addAuthProfile, authConfigSchema, authProfilesPath, authProviderFrontmatterSchema, defineAuthProvider, discoverEndpoints, eligibleProfiles, getAuthProfile, getAuthProvider, guildeAuthProvider, installConfigSchema, listAuthProfiles, listAuthProviderIds, listAuthProviders, loadAuthProfiles, methodsPresentable, parseAuthProviderManifest, parseAuthProviderManifestRaw, readKeychainToken, registerAuthProvider, removeAuthProfile, resolveAccount, resolveEndpoint, resolveStoreRef, runAuthFlow, tokenStoreSpecSchema, writeKeychainToken };
|
|
1022
|
+
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 RunFlowOptions, SPEC_NAME, SPEC_VERSION, type ServiceAuthConfig, type StoreRef, type StoredCredential, type TokenStoreSpec, 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, registerAuthProvider, removeAuthProfile, resolveAccount, resolveEndpoint, resolveStoreRef, runAuthFlow, setAuthProfileEnabled, setAuthProfileModels, tokenStoreSpecSchema, validateCreateInput, writeKeychainToken };
|