@agentproto/auth 0.1.1 → 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 +445 -1
- package/dist/index.mjs +324 -8
- 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
|
/**
|
|
@@ -540,6 +545,439 @@ declare class CredentialBroker {
|
|
|
540
545
|
}): Promise<Record<string, string>>;
|
|
541
546
|
}
|
|
542
547
|
|
|
548
|
+
/**
|
|
549
|
+
* Named auth-profile types (SPEC §1c/§3.1 — `agentproto-session-config-axes`).
|
|
550
|
+
*
|
|
551
|
+
* A profile is a named credential `{ endpoint, method, credentialRef }` that
|
|
552
|
+
* lives independently of any adapter, generalizing `providers-store`'s
|
|
553
|
+
* `ProviderEntry` (one api-key per provider, `packages/providers-store/src/
|
|
554
|
+
* index.ts:68-80`) to N named profiles per billing endpoint. `subscription|api-key` is
|
|
555
|
+
* not a session property — it demotes to the `method` facet of a profile.
|
|
556
|
+
*
|
|
557
|
+
* The secret itself is NEVER inlined here — `credentialRef` is an opaque
|
|
558
|
+
* handle into this package's own credential storage (`store/types.ts`'s
|
|
559
|
+
* `CredentialStore` / `token-store.ts`), matching how the rest of
|
|
560
|
+
* `@agentproto/auth` already fingerprints rather than echoes secrets
|
|
561
|
+
* (`broker.ts`, `KeychainStore`).
|
|
562
|
+
*/
|
|
563
|
+
/** How a profile authenticates — the narrow eligibility gate (not adapter
|
|
564
|
+
* identity). Mirrors `@agentproto/auth`'s `FlowResult.tokenKind`
|
|
565
|
+
* (`types.ts:151`): `pat` → `api-key`, `oat` → `oauth-bearer`. Extensible —
|
|
566
|
+
* new methods are additive. */
|
|
567
|
+
type AuthMethod = "oauth-bearer" | "api-key";
|
|
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. */
|
|
605
|
+
interface AuthProfile {
|
|
606
|
+
/** Stable id, unique across all profiles (the `profileRef` a session
|
|
607
|
+
* attaches). */
|
|
608
|
+
id: string;
|
|
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
|
|
613
|
+
* `@agentproto/model-catalog`, same rationale as the driver's
|
|
614
|
+
* `AgentCliDefinition.provider`. */
|
|
615
|
+
endpoint: string;
|
|
616
|
+
/** How this profile authenticates. */
|
|
617
|
+
method: AuthMethod;
|
|
618
|
+
/** Opaque handle into this package's credential storage — NEVER the secret
|
|
619
|
+
* itself. Resolved through `CredentialStore` / `token-store.ts` at use
|
|
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;
|
|
630
|
+
/** Optional human-readable name ("Jeremy Max", "work OpenRouter"). */
|
|
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;
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
/**
|
|
661
|
+
* Named auth-profile store — CRUD over `~/.agentproto/auth-profiles.json`
|
|
662
|
+
* (mode 0600), generalizing `providers-store`'s single-key-per-provider file
|
|
663
|
+
* (`packages/providers-store/src/index.ts:68-90`, `ProviderEntry`/
|
|
664
|
+
* `ProvidersFile`) to N named `AuthProfile`s per billing endpoint, keyed by `id`.
|
|
665
|
+
*
|
|
666
|
+
* This is the profile-metadata store, not the credential store: entries hold
|
|
667
|
+
* `credentialRef` (a pointer), never a secret, so — unlike `FileStore`
|
|
668
|
+
* (`store/file-store.ts`) — this file needs no encryption. Reuses the exact
|
|
669
|
+
* persistence primitives `providers-store` already established (a versioned
|
|
670
|
+
* JSON file under `~/.agentproto/`, `node:fs/promises`, mode 0600) rather
|
|
671
|
+
* than inventing a new format, just relocated to `@agentproto/auth` — the
|
|
672
|
+
* correct home for named profiles per SPEC §1c (`providers.json` is the
|
|
673
|
+
* degenerate one-key-per-provider case this generalizes).
|
|
674
|
+
*/
|
|
675
|
+
|
|
676
|
+
declare const authProfilesFileSchema: z.ZodObject<{
|
|
677
|
+
version: z.ZodLiteral<1>;
|
|
678
|
+
profiles: z.ZodRecord<z.ZodString, z.ZodPipe<z.ZodObject<{
|
|
679
|
+
id: z.ZodString;
|
|
680
|
+
vendor: z.ZodString;
|
|
681
|
+
method: z.ZodEnum<{
|
|
682
|
+
"oauth-bearer": "oauth-bearer";
|
|
683
|
+
"api-key": "api-key";
|
|
684
|
+
}>;
|
|
685
|
+
credentialRef: z.ZodOptional<z.ZodString>;
|
|
686
|
+
source: z.ZodOptional<z.ZodString>;
|
|
687
|
+
label: z.ZodOptional<z.ZodString>;
|
|
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
|
+
}>>>;
|
|
724
|
+
}, z.core.$strip>;
|
|
725
|
+
type AuthProfilesFile = z.infer<typeof authProfilesFileSchema>;
|
|
726
|
+
declare function authProfilesPath(): string;
|
|
727
|
+
declare function loadAuthProfiles(): Promise<AuthProfilesFile>;
|
|
728
|
+
/** List all profiles, optionally filtered to one billing endpoint. */
|
|
729
|
+
declare function listAuthProfiles(endpoint?: string): Promise<AuthProfile[]>;
|
|
730
|
+
/** Look up a single profile by id, or undefined if none exists. */
|
|
731
|
+
declare function getAuthProfile(id: string): Promise<AuthProfile | undefined>;
|
|
732
|
+
/** Add (or replace) a profile, keyed by its `id`. */
|
|
733
|
+
declare function addAuthProfile(profile: AuthProfile): Promise<void>;
|
|
734
|
+
/** Remove a profile by id. Returns true if it existed. */
|
|
735
|
+
declare function removeAuthProfile(id: string): Promise<boolean>;
|
|
736
|
+
|
|
737
|
+
/**
|
|
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
|
|
917
|
+
* (SPEC §1c, `agentproto-session-config-axes/SPEC.md:102-125`).
|
|
918
|
+
*
|
|
919
|
+
* profile eligible for (adapter, route) iff
|
|
920
|
+
* profile.endpoint == resolveEndpoint(adapter, route).endpoint
|
|
921
|
+
* AND profile.method ∈ methodsPresentable(adapter, route)
|
|
922
|
+
*
|
|
923
|
+
* `route` is the endpoint selector (SPEC axis #4 — direct vs a gateway mode
|
|
924
|
+
* like `moonshot`/`openrouter`), so access is deliberately downstream of it:
|
|
925
|
+
* which endpoint (and thus which profiles) are eligible changes when route
|
|
926
|
+
* changes. `AdapterAuthManifest` is a narrow, package-local projection of
|
|
927
|
+
* exactly what this predicate needs from an adapter's real AIP-45 manifest
|
|
928
|
+
* (`packages/driver/agent-cli/src/types.ts`'s `AgentCliDefinition`) — this
|
|
929
|
+
* package intentionally does not depend on `@agentproto/driver-agent-cli`
|
|
930
|
+
* (wrong dependency direction; drivers consume auth, not vice versa), so the
|
|
931
|
+
* runtime is the one that will later project a real manifest into this
|
|
932
|
+
* shape (out of scope here — foundation only, no live spawn-path wiring).
|
|
933
|
+
*
|
|
934
|
+
* `methodsByRoute` is the static per-endpoint method table ADR'd in SPEC §3.4:
|
|
935
|
+
* "which auth methods this adapter can present for a resolved route." It is
|
|
936
|
+
* the derivable replacement for two hand-maintained artifacts SPEC §1c calls
|
|
937
|
+
* out for eventual removal — the per-adapter `authSubscription` boolean
|
|
938
|
+
* (`adapters/claude-code/src/index.ts:90-95`) and curatorial vendor deny
|
|
939
|
+
* lists (`adapters/hermes/HERMES.md:40-42`) — neither of which this PR
|
|
940
|
+
* touches; `authSubscription` stays exactly as-is (see the comment on it in
|
|
941
|
+
* `spawn-defaults.ts:345` — this module is additive, not a replacement).
|
|
942
|
+
*
|
|
943
|
+
* ACP `authenticate` is NOT a live discovery source for this table (the
|
|
944
|
+
* server handler is a stub, `packages/acp/src/server/index.ts:69`) — method
|
|
945
|
+
* discovery is this static table, not runtime negotiation (SPEC §3.7).
|
|
946
|
+
*/
|
|
947
|
+
|
|
948
|
+
/** A narrow, package-local projection of an adapter's declared auth
|
|
949
|
+
* capability — enough to resolve (adapter, route) → endpoint and the auth
|
|
950
|
+
* methods presentable on that route. Not the real AIP-45 manifest type. */
|
|
951
|
+
interface AdapterAuthManifest {
|
|
952
|
+
/** Adapter id (e.g. "claude-code", "hermes"), for error messages only. */
|
|
953
|
+
id: string;
|
|
954
|
+
/** route id (e.g. "direct", or a gateway mode id like "moonshot") →
|
|
955
|
+
* the billing endpoint used when spawned on that route. */
|
|
956
|
+
endpointByRoute: Readonly<Record<string, string>>;
|
|
957
|
+
/** route id → the auth methods this adapter can present when spawned on
|
|
958
|
+
* that route — the method-side of the eligibility predicate. */
|
|
959
|
+
methodsByRoute: Readonly<Record<string, readonly AuthMethod[]>>;
|
|
960
|
+
}
|
|
961
|
+
/** Resolve which billing endpoint a given (adapter, route) pair uses. Throws
|
|
962
|
+
* when the manifest declares no endpoint for `route` — an unresolvable route
|
|
963
|
+
* is a caller bug (a bad/unknown route id), not a "no profiles eligible"
|
|
964
|
+
* case, so this fails loud rather than returning an empty endpoint. */
|
|
965
|
+
declare function resolveEndpoint(manifest: AdapterAuthManifest, route: string): {
|
|
966
|
+
endpoint: string;
|
|
967
|
+
};
|
|
968
|
+
/** Which auth methods `manifest`'s adapter can present on `route`. Empty
|
|
969
|
+
* (never throws) when the route is declared for vendor resolution but has
|
|
970
|
+
* no methods table entry — that's "no eligible profiles", a legitimate
|
|
971
|
+
* eligibility outcome, not an error. */
|
|
972
|
+
declare function methodsPresentable(manifest: AdapterAuthManifest, route: string): AuthMethod[];
|
|
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). */
|
|
979
|
+
declare function eligibleProfiles(profiles: readonly AuthProfile[], manifest: AdapterAuthManifest, route: string): AuthProfile[];
|
|
980
|
+
|
|
543
981
|
/** Guilde AI company platform.
|
|
544
982
|
*
|
|
545
983
|
* Authenticates via the AIP-50 service-auth claim ceremony: browser opens,
|
|
@@ -570,9 +1008,15 @@ declare const BUILTIN_AUTH_PROVIDERS: readonly AuthProviderHandle[];
|
|
|
570
1008
|
* KeychainStore / MemoryStore / FileStore — built-in CredentialStore backends
|
|
571
1009
|
* resolveStoreRef(spec, server) — map a TokenStoreSpec to a StoreRef
|
|
572
1010
|
* CredentialBroker — path → ready-to-use auth headers
|
|
1011
|
+
* AuthProfile / AuthMethod — named, endpoint-scoped credential ref
|
|
1012
|
+
* listAuthProfiles/getAuthProfile/
|
|
1013
|
+
* addAuthProfile/removeAuthProfile — named-profile store CRUD
|
|
1014
|
+
* resolveEndpoint/methodsPresentable/
|
|
1015
|
+
* eligibleProfiles — (adapter × route) → endpoint + the
|
|
1016
|
+
* profile eligibility predicate
|
|
573
1017
|
*/
|
|
574
1018
|
|
|
575
1019
|
declare const SPEC_NAME = "agentauth";
|
|
576
1020
|
declare const SPEC_VERSION = "v1";
|
|
577
1021
|
|
|
578
|
-
export { type AuthConfig, 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, authConfigSchema, authProviderFrontmatterSchema, defineAuthProvider, discoverEndpoints, getAuthProvider, guildeAuthProvider, installConfigSchema, listAuthProviderIds, listAuthProviders, parseAuthProviderManifest, parseAuthProviderManifestRaw, readKeychainToken, registerAuthProvider, resolveAccount, 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 };
|