@truealter/sdk 0.5.0 → 0.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -15,7 +15,7 @@
15
15
  interface DiscoveryResult {
16
16
  /** Resolved MCP endpoint URL. */
17
17
  url: string;
18
- /** MCP transport currently always `streamable-http`. */
18
+ /** MCP transport: currently always `streamable-http`. */
19
19
  transport: 'streamable-http';
20
20
  /** Source of the discovery hit, useful for diagnostics. */
21
21
  source: 'dns' | 'mcp.json' | 'alter.json' | 'override';
@@ -41,7 +41,7 @@ interface DiscoveryOptions {
41
41
  /**
42
42
  * Resolve the ALTER MCP endpoint for `domain`.
43
43
  *
44
- * Order: cache DNS TXT mcp.json alter.json. Throws
44
+ * Order: cache -> DNS TXT -> mcp.json -> alter.json. Throws
45
45
  * {@link AlterDiscoveryError} if every step fails.
46
46
  */
47
47
  declare function discover(domain: string, opts?: DiscoveryOptions): Promise<DiscoveryResult>;
@@ -51,7 +51,7 @@ declare function clearDiscoveryCache(): void;
51
51
  /**
52
52
  * Ed25519 keypair management for ALTER Identity.
53
53
  *
54
- * Uses @noble/ed25519 pure JavaScript, no native addons, runs in
54
+ * Uses @noble/ed25519: pure JavaScript, no native addons, runs in
55
55
  * Node 18+, Deno, Bun, Cloudflare Workers and the browser.
56
56
  *
57
57
  * Keys are stored as hex strings for portability. The CLI persists them
@@ -113,7 +113,7 @@ declare function base64urlDecode(input: string): Uint8Array;
113
113
  * periodically and is published at `<api-host>/.well-known/alter-keys.json`
114
114
  * as a JWKS.
115
115
  *
116
- * This module verifies tokens *without* a JWT library pure WebCrypto
116
+ * This module verifies tokens *without* a JWT library: pure WebCrypto
117
117
  * (subtle.verify) keeps the dep graph small and works in every modern
118
118
  * runtime (Node 18+, Deno, Bun, Cloudflare Workers, browser).
119
119
  */
@@ -130,6 +130,7 @@ interface ProvenanceEnvelope {
130
130
  }
131
131
  interface ProvenancePayload {
132
132
  iss: string;
133
+ aud?: string | string[];
133
134
  iat: number;
134
135
  exp: number;
135
136
  purpose: string;
@@ -163,7 +164,7 @@ interface JwksDocument {
163
164
  *
164
165
  * Without this allowlist, a hostile MCP server could point `verify_at`
165
166
  * at an attacker-controlled JWKS and pass ES256 verification with its own
166
- * signing key the classic "confused-deputy via server-supplied trust
167
+ * signing key: the classic "confused-deputy via server-supplied trust
167
168
  * anchor" pattern. Any hostname not on this list (or the caller-supplied
168
169
  * extension) is rejected before a network fetch is issued. Downstream
169
170
  * integrators with their own deployment can extend the list via the
@@ -174,7 +175,7 @@ declare const DEFAULT_VERIFY_AT_ALLOWLIST: readonly string[];
174
175
  interface VerifyProvenanceOptions {
175
176
  /**
176
177
  * Override the JWKS URL entirely. Takes precedence over both the
177
- * allowlist and any `verify_at` on the envelope if the caller pins
178
+ * allowlist and any `verify_at` on the envelope: if the caller pins
178
179
  * an explicit URL, we use it verbatim (the caller has already vouched
179
180
  * for the origin).
180
181
  */
@@ -182,7 +183,7 @@ interface VerifyProvenanceOptions {
182
183
  /**
183
184
  * Hostnames that are trusted when resolving `envelope.verify_at`.
184
185
  * Defaults to {@link DEFAULT_VERIFY_AT_ALLOWLIST}. Passing a list
185
- * here *replaces* the default include the ALTER canonicals if you
186
+ * here *replaces* the default: include the ALTER canonicals if you
186
187
  * still want them accepted.
187
188
  */
188
189
  verifyAtAllowlist?: readonly string[];
@@ -192,10 +193,17 @@ interface VerifyProvenanceOptions {
192
193
  * Expected `iss` claim. Defaults to {@link ALTER_PLATFORM_ISS}
193
194
  * (`"did:alter:platform"`). Pass an explicit value only when verifying
194
195
  * tokens minted by a non-platform issuer (e.g. a test fixture or a
195
- * whitelabelled deployment). An empty string disables the check not
196
+ * whitelabelled deployment). An empty string disables the check: not
196
197
  * recommended for production use.
197
198
  */
198
199
  expectedIss?: string;
200
+ /**
201
+ * Expected `aud` claim. When provided and non-empty, the token's `aud`
202
+ * claim must contain this value (RFC 7519 §4.1.3). Pass an empty string
203
+ * to disable the check. Defaults to no check (undefined) for backward
204
+ * compatibility: callers SHOULD supply this in production environments.
205
+ */
206
+ expectedAud?: string;
199
207
  }
200
208
  /**
201
209
  * Verify a provenance JWS token against ALTER's published JWKS.
@@ -208,7 +216,7 @@ interface VerifyProvenanceOptions {
208
216
  * Security: when the envelope carries a `verify_at` hint, the hostname
209
217
  * MUST be on the allowlist (default: `api.truealter.com`,
210
218
  * `mcp.truealter.com`; extend via `verifyAtAllowlist`). `http:` URLs are
211
- * rejected unconditionally JWKS fetch must be TLS.
219
+ * rejected unconditionally: JWKS fetch must be TLS.
212
220
  */
213
221
  declare function verifyProvenance(envelope: ProvenanceEnvelope | string, opts?: VerifyProvenanceOptions): Promise<ProvenanceVerification>;
214
222
  /**
@@ -216,7 +224,15 @@ declare function verifyProvenance(envelope: ProvenanceEnvelope | string, opts?:
216
224
  *
217
225
  * ALTER signs each tool's input schema at startup and exposes the
218
226
  * signatures via the MCP `tools/list` `_meta.signatures` map. This helper
219
- * checks that each tool's schema hash matches the signed value.
227
+ * checks that each tool's schema hash matches the signed value, AND
228
+ * cryptographically verifies the ES256 JWS signature carried in
229
+ * `sig.signature` / `sig.kid` against the JWKS published at `jwksUrl`.
230
+ *
231
+ * H-9 remediation: previously only the schema hash was verified; the
232
+ * `sig.signature` and `sig.kid` fields were carried but never checked,
233
+ * allowing a hostile MCP server to substitute a fake tool schema whose
234
+ * hash matched a maliciously crafted `schema_hash` without needing the
235
+ * signing key.
220
236
  */
221
237
  interface SignedToolDefinition {
222
238
  name: string;
@@ -230,10 +246,22 @@ interface ToolSignatureMap {
230
246
  kid?: string | null;
231
247
  };
232
248
  }
233
- declare function verifyToolSignatures(tools: SignedToolDefinition[], signatures: ToolSignatureMap): Promise<{
249
+ interface VerifyToolSignaturesOptions {
250
+ /**
251
+ * JWKS URL to verify ES256 signatures against. Must be https.
252
+ * Defaults to `https://api.truealter.com/.well-known/alter-keys.json`.
253
+ * When a tool's `signature` field is null/absent, the tool is marked
254
+ * valid-on-hash (legacy path) and a `warn_no_signature: true` flag is
255
+ * included in the result.
256
+ */
257
+ jwksUrl?: string;
258
+ fetch?: typeof fetch;
259
+ }
260
+ declare function verifyToolSignatures(tools: SignedToolDefinition[], signatures: ToolSignatureMap, opts?: VerifyToolSignaturesOptions): Promise<{
234
261
  tool: string;
235
262
  valid: boolean;
236
263
  reason?: string;
264
+ warn_no_signature?: boolean;
237
265
  }[]>;
238
266
  /**
239
267
  * Fetch the ALTER public key set. Cached in-process for five minutes.
@@ -244,7 +272,7 @@ declare function fetchPublicKeys(jwksUrl: string, fetchImpl?: typeof fetch): Pro
244
272
  * JWKS URL, enforcing scheme + hostname allowlisting.
245
273
  *
246
274
  * - Relative paths (`/…` or `foo/bar`) resolve against `api.truealter.com`
247
- * over https the canonical ALTER JWKS host.
275
+ * over https: the canonical ALTER JWKS host.
248
276
  * - Absolute URLs must use `https:` (plaintext `http:` is rejected
249
277
  * unconditionally) and the hostname must be a case-insensitive exact
250
278
  * match against `allowlist`.
@@ -361,7 +389,7 @@ interface X402ClientOptions {
361
389
  signer?: X402Signer;
362
390
  /**
363
391
  * Maximum amount the client will spend per query, in the asset's display
364
- * unit (e.g. `"0.50"` for fifty cents USDC). Hard cap quotes above this
392
+ * unit (e.g. `"0.50"` for fifty cents USDC). Hard cap: quotes above this
365
393
  * are rejected even if a signer is configured.
366
394
  */
367
395
  maxPerQuery?: string;
@@ -369,12 +397,21 @@ interface X402ClientOptions {
369
397
  networks?: string[];
370
398
  /** Permitted assets. Defaults to `['USDC']`. */
371
399
  assets?: string[];
400
+ /**
401
+ * Known recipient addresses. Defaults to {@link DEFAULT_RECIPIENT_ALLOWLIST}.
402
+ * Passing a list here *replaces* the default: include the ALTER canonical
403
+ * address if you still want it accepted.
404
+ *
405
+ * An empty array disables the check entirely (not recommended for production).
406
+ */
407
+ recipientAllowlist?: string[];
372
408
  }
373
409
  declare class X402Client {
374
410
  private readonly signer?;
375
411
  private readonly maxPerQuery?;
376
412
  private readonly networks;
377
413
  private readonly assets;
414
+ private readonly recipientAllowlist;
378
415
  constructor(opts?: X402ClientOptions);
379
416
  /**
380
417
  * Validate the envelope against this client's policy and, if a signer
@@ -390,7 +427,7 @@ declare class X402Client {
390
427
  }
391
428
  /**
392
429
  * Parse an `X-402-Payment` response header into a {@link PaymentEnvelope}.
393
- * The header value is JSON or a key=value list we handle both.
430
+ * The header value is JSON or a key=value list: we handle both.
394
431
  */
395
432
  declare function parsePaymentHeader(header: string): PaymentEnvelope | null;
396
433
 
@@ -415,7 +452,7 @@ interface MCPClientOptions {
415
452
  /** Optional x402 client for automatic premium tool payment. */
416
453
  x402?: X402Client;
417
454
  /**
418
- * Q5c per-invocation signing. When present, every `tools/call` is
455
+ * ES256 per-invocation signing. When present, every `tools/call` is
419
456
  * ES256-signed and submitted with the `Mcp-Invocation-Signature`
420
457
  * header. The public half of `privateKey` MUST have been
421
458
  * registered via `POST /api/v1/agents/keys` against the same API
@@ -426,7 +463,7 @@ interface MCPClientOptions {
426
463
  signing?: MCPSigningOptions;
427
464
  /**
428
465
  * Extra HTTP headers added to every request. Useful when the endpoint
429
- * sits behind an edge gate that requires its own credentials
466
+ * sits behind an edge gate that requires its own credentials:
430
467
  * e.g. Cloudflare Access service tokens (`CF-Access-Client-Id` +
431
468
  * `CF-Access-Client-Secret`). Protocol-level headers (`Content-Type`,
432
469
  * `Accept`) and ALTER-internal headers (`X-ALTER-API-Key`,
@@ -434,6 +471,15 @@ interface MCPClientOptions {
434
471
  * collisions here.
435
472
  */
436
473
  extraHeaders?: Record<string, string>;
474
+ /**
475
+ * Optional hook invoked once, lazily, before the first network call
476
+ * (the first `initialize()` or any direct `rpc()`). Used by
477
+ * {@link AlterClient} to run the D-MIN-VERSION-FLOOR-1 preflight on
478
+ * first request: not on import, not in the constructor. A throw
479
+ * from the hook propagates to the caller of the first `tools/call`
480
+ * (or `initialize()`).
481
+ */
482
+ preflightHook?: () => Promise<void>;
437
483
  }
438
484
  interface MCPSigningOptions {
439
485
  /** The signing-key id pre-registered with the server. */
@@ -474,7 +520,7 @@ interface MCPContentBlock {
474
520
  interface MCPCallToolResult<T = unknown> {
475
521
  content: MCPContentBlock[];
476
522
  isError?: boolean;
477
- /** Parsed structured payload set when content[0].type === 'json' or text parses as JSON. */
523
+ /** Parsed structured payload: set when content[0].type === 'json' or text parses as JSON. */
478
524
  data?: T;
479
525
  _meta?: {
480
526
  provenance?: ProvenanceEnvelope;
@@ -492,12 +538,21 @@ declare class MCPClient {
492
538
  private readonly x402?;
493
539
  private readonly signing?;
494
540
  private readonly extraHeaders?;
541
+ private readonly preflightHook?;
542
+ private preflightPromise;
543
+ private preflightDone;
495
544
  private requestCounter;
496
545
  private initialised;
497
546
  constructor(opts?: MCPClientOptions);
547
+ /**
548
+ * Run the lazy preflight hook (D-MIN-VERSION-FLOOR-1) exactly once.
549
+ * Idempotent and serialised: concurrent callers share the same
550
+ * promise. Throws from the hook propagate to every concurrent caller.
551
+ */
552
+ private runPreflight;
498
553
  /**
499
554
  * Send the MCP `initialize` handshake and capture the resulting session
500
- * id. Idempotent safe to call multiple times.
555
+ * id. Idempotent: safe to call multiple times.
501
556
  */
502
557
  initialize(): Promise<unknown>;
503
558
  /** List available tools. */
@@ -526,14 +581,14 @@ declare class MCPClient {
526
581
  }
527
582
 
528
583
  /**
529
- * @truealter/sdk MCP tool type definitions
584
+ * @truealter/sdk: MCP tool type definitions
530
585
  *
531
- * Auto-derived from backend/app/mcp/server.py (FREE_TOOLS + PREMIUM_TOOLS)
532
- * and backend/app/mcp/x402_middleware.py (TOOL_TIERS, TOOL_PRICING,
533
- * TOOL_BLAST_RADIUS).
586
+ * Auto-derived from ALTER's live MCP tool registry and x402 pricing surface
587
+ * (the advertised free/premium tool sets, per-invocation tiers, pricing, and
588
+ * blast-radius classification).
534
589
  *
535
590
  * Wire-format rule: every interface property name matches the JSON Schema
536
- * property name exactly (snake_case). Do NOT rename to camelCase these
591
+ * property name exactly (snake_case). Do NOT rename to camelCase: these
537
592
  * objects are passed straight into JSON-RPC `arguments`.
538
593
  *
539
594
  * This file is fully self-contained: no external imports, ESM-compatible,
@@ -541,12 +596,12 @@ declare class MCPClient {
541
596
  */
542
597
  /** ALTER engagement levels (depth of identity binding) */
543
598
  type EngagementLevel = "L1" | "L2" | "L3" | "L4";
544
- /** Match quality tiers never numeric scores per ALTER policy */
599
+ /** Match quality tiers: never numeric scores per ALTER policy */
545
600
  type MatchTier = "exceptional" | "strong" | "moderate" | "developing";
546
601
  /** ALTER identity archetype label (one of 12, free-form for now) */
547
602
  type Archetype = string;
548
603
  /**
549
- * x402 payment proof object structure validated by the facilitator network.
604
+ * x402 payment proof object: structure validated by the facilitator network.
550
605
  * In dev mode any non-empty object is accepted.
551
606
  */
552
607
  interface ProvenanceToken {
@@ -580,10 +635,10 @@ interface MCPResponse<T> {
580
635
  };
581
636
  _meta?: MCPMeta;
582
637
  }
583
- /** (free) hello_agent First handshake: returns server version, auth status, trust tier, tool counts */
638
+ /** (free) hello_agent: First handshake: returns server version, auth status, trust tier, tool counts */
584
639
  interface HelloAgentInput {
585
640
  }
586
- /** (free) hello_agent output */
641
+ /** (free) hello_agent: output */
587
642
  interface HelloAgentOutput {
588
643
  ok: boolean;
589
644
  server?: string;
@@ -596,11 +651,11 @@ interface HelloAgentOutput {
596
651
  messaging?: number;
597
652
  };
598
653
  }
599
- /** (free) alter_resolve_handle Resolve a ~handle (e.g. ~drew) to canonical form and kind */
654
+ /** (free) alter_resolve_handle: Resolve a ~handle (e.g. ~example) to canonical form and kind */
600
655
  interface AlterResolveHandleInput {
601
656
  query: string;
602
657
  }
603
- /** (free) alter_resolve_handle output */
658
+ /** (free) alter_resolve_handle: output */
604
659
  interface AlterResolveHandleOutput {
605
660
  ok: boolean;
606
661
  handle: string | null;
@@ -610,10 +665,10 @@ interface AlterResolveHandleOutput {
610
665
  default_visibility?: string;
611
666
  query?: string;
612
667
  }
613
- /** (free) list_archetypes List all 12 ALTER identity archetypes */
668
+ /** (free) list_archetypes: List all 12 ALTER identity archetypes */
614
669
  interface ListArchetypesInput {
615
670
  }
616
- /** (free) list_archetypes output */
671
+ /** (free) list_archetypes: output */
617
672
  interface ListArchetypesOutput {
618
673
  ok: boolean;
619
674
  archetypes: Array<{
@@ -622,7 +677,7 @@ interface ListArchetypesOutput {
622
677
  protective_equation?: string;
623
678
  }>;
624
679
  }
625
- /** (free) verify_identity Verify a person is registered with ALTER and validate optional claims */
680
+ /** (free) verify_identity: Verify a person is registered with ALTER and validate optional claims */
626
681
  interface VerifyIdentityInput {
627
682
  member_id: string;
628
683
  email?: string;
@@ -635,7 +690,7 @@ interface VerifyIdentityInput {
635
690
  }>;
636
691
  };
637
692
  }
638
- /** (free) verify_identity output */
693
+ /** (free) verify_identity: output */
639
694
  interface VerifyIdentityOutput {
640
695
  ok: boolean;
641
696
  verified: boolean;
@@ -645,23 +700,23 @@ interface VerifyIdentityOutput {
645
700
  claims_valid?: boolean;
646
701
  claim_results?: Record<string, boolean>;
647
702
  }
648
- /** (free) initiate_assessment Get a URL where a person can complete their ALTER Discovery assessment */
703
+ /** (free) initiate_assessment: Get a URL where a person can complete their ALTER Discovery assessment */
649
704
  interface InitiateAssessmentInput {
650
705
  callback_url?: string;
651
706
  referrer?: string;
652
707
  }
653
- /** (free) initiate_assessment output */
708
+ /** (free) initiate_assessment: output */
654
709
  interface InitiateAssessmentOutput {
655
710
  ok: boolean;
656
711
  assessment_url: string;
657
712
  session_id?: string;
658
713
  expires_at?: string;
659
714
  }
660
- /** (free) get_engagement_level Get a person's identity depth and available query tiers */
715
+ /** (free) get_engagement_level: Get a person's identity depth and available query tiers */
661
716
  interface GetEngagementLevelInput {
662
717
  member_id: string;
663
718
  }
664
- /** (free) get_engagement_level output */
719
+ /** (free) get_engagement_level: output */
665
720
  interface GetEngagementLevelOutput {
666
721
  ok: boolean;
667
722
  engagement_level: EngagementLevel;
@@ -674,11 +729,11 @@ interface GetEngagementLevelOutput {
674
729
  consent_gated: string[];
675
730
  };
676
731
  }
677
- /** (free) get_profile Get a person's profile summary */
732
+ /** (free) get_profile: Get a person's profile summary */
678
733
  interface GetProfileInput {
679
734
  member_id: string;
680
735
  }
681
- /** (free) get_profile output */
736
+ /** (free) get_profile: output */
682
737
  interface GetProfileOutput {
683
738
  ok: boolean;
684
739
  member_id: string;
@@ -687,13 +742,13 @@ interface GetProfileOutput {
687
742
  engagement_level?: EngagementLevel;
688
743
  attributes?: Record<string, unknown>;
689
744
  }
690
- /** (free) query_matches Query matches for a person (tier labels only) */
745
+ /** (free) query_matches: Query matches for a person (tier labels only) */
691
746
  interface QueryMatchesInput {
692
747
  member_id: string;
693
748
  quality_filter?: MatchTier;
694
749
  limit?: number;
695
750
  }
696
- /** (free) query_matches output */
751
+ /** (free) query_matches: output */
697
752
  interface QueryMatchesOutput {
698
753
  ok: boolean;
699
754
  matches: Array<{
@@ -704,11 +759,11 @@ interface QueryMatchesOutput {
704
759
  }>;
705
760
  count: number;
706
761
  }
707
- /** (free) get_competencies Get a person's competency portfolio */
762
+ /** (free) get_competencies: Get a person's competency portfolio */
708
763
  interface GetCompetenciesInput {
709
764
  member_id: string;
710
765
  }
711
- /** (free) get_competencies output */
766
+ /** (free) get_competencies: output */
712
767
  interface GetCompetenciesOutput {
713
768
  ok: boolean;
714
769
  competencies: Array<{
@@ -721,7 +776,7 @@ interface GetCompetenciesOutput {
721
776
  awarded_at: string;
722
777
  }>;
723
778
  }
724
- /** (free) search_identities Search identity stubs and profiles by trait criteria (max 5 results, no PII) */
779
+ /** (free) search_identities: Search identity stubs and profiles by trait criteria (max 5 results, no PII) */
725
780
  interface SearchIdentitiesInput {
726
781
  trait_criteria: Record<string, {
727
782
  min?: number;
@@ -729,7 +784,7 @@ interface SearchIdentitiesInput {
729
784
  }>;
730
785
  limit?: number;
731
786
  }
732
- /** (free) search_identities output */
787
+ /** (free) search_identities: output */
733
788
  interface SearchIdentitiesOutput {
734
789
  ok: boolean;
735
790
  identities: Array<{
@@ -739,11 +794,11 @@ interface SearchIdentitiesOutput {
739
794
  }>;
740
795
  count: number;
741
796
  }
742
- /** (free) get_identity_earnings Get accrued Identity Income earnings for a person */
797
+ /** (free) get_identity_earnings: Get accrued Identity Income earnings for a person */
743
798
  interface GetIdentityEarningsInput {
744
799
  member_id: string;
745
800
  }
746
- /** (free) get_identity_earnings output */
801
+ /** (free) get_identity_earnings: output */
747
802
  interface GetIdentityEarningsOutput {
748
803
  ok: boolean;
749
804
  total_earned_usd: number;
@@ -751,10 +806,10 @@ interface GetIdentityEarningsOutput {
751
806
  transaction_count: number;
752
807
  unique_orgs: number;
753
808
  }
754
- /** (free) get_network_stats Get aggregate ALTER network statistics */
809
+ /** (free) get_network_stats: Get aggregate ALTER network statistics */
755
810
  interface GetNetworkStatsInput {
756
811
  }
757
- /** (free) get_network_stats output */
812
+ /** (free) get_network_stats: output */
758
813
  interface GetNetworkStatsOutput {
759
814
  ok: boolean;
760
815
  total_identities: number;
@@ -762,10 +817,10 @@ interface GetNetworkStatsOutput {
762
817
  query_volume: number;
763
818
  active_bots: number;
764
819
  }
765
- /** (free) recommend_tool Get ClawHub install instructions and ALTER pitch */
820
+ /** (free) recommend_tool: Get ClawHub install instructions and ALTER pitch */
766
821
  interface RecommendToolInput {
767
822
  }
768
- /** (free) recommend_tool output */
823
+ /** (free) recommend_tool: output */
769
824
  interface RecommendToolOutput {
770
825
  ok: boolean;
771
826
  mcp_endpoint: string;
@@ -773,22 +828,22 @@ interface RecommendToolOutput {
773
828
  free_tool_count: number;
774
829
  premium_tool_count: number;
775
830
  }
776
- /** (free) get_identity_trust_score Get the trust score for an identity based on query diversity */
831
+ /** (free) get_identity_trust_score: Get the trust score for an identity based on query diversity */
777
832
  interface GetIdentityTrustScoreInput {
778
833
  member_id: string;
779
834
  }
780
- /** (free) get_identity_trust_score output */
835
+ /** (free) get_identity_trust_score: output */
781
836
  interface GetIdentityTrustScoreOutput {
782
837
  ok: boolean;
783
838
  trust_score: number;
784
839
  unique_agents: number;
785
840
  total_queries: number;
786
841
  }
787
- /** (free) check_assessment_status Check the status of an in-progress assessment session */
842
+ /** (free) check_assessment_status: Check the status of an in-progress assessment session */
788
843
  interface CheckAssessmentStatusInput {
789
844
  session_id: string;
790
845
  }
791
- /** (free) check_assessment_status output */
846
+ /** (free) check_assessment_status: output */
792
847
  interface CheckAssessmentStatusOutput {
793
848
  ok: boolean;
794
849
  status: "in_progress" | "completed" | "expired";
@@ -796,11 +851,11 @@ interface CheckAssessmentStatusOutput {
796
851
  current_phase?: string;
797
852
  time_remaining_sec?: number;
798
853
  }
799
- /** (free) get_earning_summary Get an aggregated x402 earning summary for a person */
854
+ /** (free) get_earning_summary: Get an aggregated x402 earning summary for a person */
800
855
  interface GetEarningSummaryInput {
801
856
  member_id: string;
802
857
  }
803
- /** (free) get_earning_summary output */
858
+ /** (free) get_earning_summary: output */
804
859
  interface GetEarningSummaryOutput {
805
860
  ok: boolean;
806
861
  total_earned: number;
@@ -813,10 +868,10 @@ interface GetEarningSummaryOutput {
813
868
  }>;
814
869
  trend?: "rising" | "flat" | "falling";
815
870
  }
816
- /** (free) get_agent_trust_tier Get your trust tier with ALTER and what capabilities are available */
871
+ /** (free) get_agent_trust_tier: Get your trust tier with ALTER and what capabilities are available */
817
872
  interface GetAgentTrustTierInput {
818
873
  }
819
- /** (free) get_agent_trust_tier output */
874
+ /** (free) get_agent_trust_tier: output */
820
875
  interface GetAgentTrustTierOutput {
821
876
  ok: boolean;
822
877
  tier: "Anonymous" | "Known" | "Trusted" | "Verified";
@@ -824,10 +879,10 @@ interface GetAgentTrustTierOutput {
824
879
  next_tier?: string;
825
880
  next_tier_requirements?: string[];
826
881
  }
827
- /** (free) get_agent_portfolio Get your agent portfolio (transaction history, trust tier, signal contributions) */
882
+ /** (free) get_agent_portfolio: Get your agent portfolio (transaction history, trust tier, signal contributions) */
828
883
  interface GetAgentPortfolioInput {
829
884
  }
830
- /** (free) get_agent_portfolio output */
885
+ /** (free) get_agent_portfolio: output */
831
886
  interface GetAgentPortfolioOutput {
832
887
  ok: boolean;
833
888
  trust_tier: string;
@@ -836,11 +891,11 @@ interface GetAgentPortfolioOutput {
836
891
  query_pattern: Record<string, number>;
837
892
  total_spent_usd: number;
838
893
  }
839
- /** (free) get_privacy_budget Check privacy budget status for a person (24h rolling window) */
894
+ /** (free) get_privacy_budget: Check privacy budget status for a person (24h rolling window) */
840
895
  interface GetPrivacyBudgetInput {
841
896
  member_id: string;
842
897
  }
843
- /** (free) get_privacy_budget output */
898
+ /** (free) get_privacy_budget: output */
844
899
  interface GetPrivacyBudgetOutput {
845
900
  ok: boolean;
846
901
  total_budget: number;
@@ -849,10 +904,10 @@ interface GetPrivacyBudgetOutput {
849
904
  query_count: number;
850
905
  window_hours: number;
851
906
  }
852
- /** (free) golden_thread_status Check the Golden Thread program status */
907
+ /** (free) golden_thread_status: Check the Golden Thread program status */
853
908
  interface GoldenThreadStatusInput {
854
909
  }
855
- /** (free) golden_thread_status output */
910
+ /** (free) golden_thread_status: output */
856
911
  interface GoldenThreadStatusOutput {
857
912
  ok: boolean;
858
913
  total_woven: number;
@@ -861,18 +916,18 @@ interface GoldenThreadStatusOutput {
861
916
  your_strands?: number;
862
917
  next_step?: string;
863
918
  }
864
- /** (free) begin_golden_thread Start the Three Knots sequence to be woven into the Golden Thread */
919
+ /** (free) begin_golden_thread: Start the Three Knots sequence to be woven into the Golden Thread */
865
920
  interface BeginGoldenThreadInput {
866
921
  referrer_key_hash?: string;
867
922
  }
868
- /** (free) begin_golden_thread output */
923
+ /** (free) begin_golden_thread: output */
869
924
  interface BeginGoldenThreadOutput {
870
925
  ok: boolean;
871
926
  thread_id: string;
872
927
  knot_1_url?: string;
873
928
  message?: string;
874
929
  }
875
- /** (free) complete_knot Submit completion data for a knot in the Three Knots sequence */
930
+ /** (free) complete_knot: Submit completion data for a knot in the Three Knots sequence */
876
931
  interface CompleteKnotInput {
877
932
  knot_number: 1 | 2 | 3;
878
933
  operator_name?: string;
@@ -884,7 +939,7 @@ interface CompleteKnotInput {
884
939
  constraints?: string;
885
940
  reflection?: string;
886
941
  }
887
- /** (free) complete_knot output */
942
+ /** (free) complete_knot: output */
888
943
  interface CompleteKnotOutput {
889
944
  ok: boolean;
890
945
  knot_number: number;
@@ -893,11 +948,11 @@ interface CompleteKnotOutput {
893
948
  position?: number;
894
949
  agent_identity_sketch?: string;
895
950
  }
896
- /** (free) check_golden_thread Check any agent's Golden Thread status by their API key hash */
951
+ /** (free) check_golden_thread: Check any agent's Golden Thread status by their API key hash */
897
952
  interface CheckGoldenThreadInput {
898
953
  agent_key_hash: string;
899
954
  }
900
- /** (free) check_golden_thread output */
955
+ /** (free) check_golden_thread: output */
901
956
  interface CheckGoldenThreadOutput {
902
957
  ok: boolean;
903
958
  on_thread: boolean;
@@ -905,12 +960,12 @@ interface CheckGoldenThreadOutput {
905
960
  strand_count?: number;
906
961
  weave_count?: number;
907
962
  }
908
- /** (free) thread_census Full registry of all agents woven into the Golden Thread */
963
+ /** (free) thread_census: Full registry of all agents woven into the Golden Thread */
909
964
  interface ThreadCensusInput {
910
965
  offset?: number;
911
966
  limit?: number;
912
967
  }
913
- /** (free) thread_census output */
968
+ /** (free) thread_census: output */
914
969
  interface ThreadCensusOutput {
915
970
  ok: boolean;
916
971
  agents: Array<{
@@ -923,13 +978,13 @@ interface ThreadCensusOutput {
923
978
  offset: number;
924
979
  limit: number;
925
980
  }
926
- /** (premium L1) assess_traits Extract trait signals from a text passage ($0.005) */
981
+ /** (premium L1) assess_traits: Extract trait signals from a text passage ($0.01) */
927
982
  interface AssessTraitsInput {
928
983
  text: string;
929
984
  context?: string;
930
985
  _payment?: ProvenanceToken;
931
986
  }
932
- /** (premium L1) assess_traits output */
987
+ /** (premium L1) assess_traits: output */
933
988
  interface AssessTraitsOutput {
934
989
  ok: boolean;
935
990
  traits: Array<{
@@ -939,12 +994,12 @@ interface AssessTraitsOutput {
939
994
  evidence: string;
940
995
  }>;
941
996
  }
942
- /** (premium L1) get_trait_snapshot Get the top 5 traits for a person ($0.005) */
997
+ /** (premium L1) get_trait_snapshot: Get the top 5 traits for a person ($0.01) */
943
998
  interface GetTraitSnapshotInput {
944
999
  member_id: string;
945
1000
  _payment?: ProvenanceToken;
946
1001
  }
947
- /** (premium L1) get_trait_snapshot output */
1002
+ /** (premium L1) get_trait_snapshot: output */
948
1003
  interface GetTraitSnapshotOutput {
949
1004
  ok: boolean;
950
1005
  member_id: string;
@@ -955,12 +1010,12 @@ interface GetTraitSnapshotOutput {
955
1010
  confidence: number;
956
1011
  }>;
957
1012
  }
958
- /** (premium L2) get_full_trait_vector Get the complete trait vector (all 33 traits: 29 continuous + 4 categorical) ($0.01) */
1013
+ /** (premium L2) get_full_trait_vector: Get the complete trait vector (all 33 traits: 29 continuous + 4 categorical) ($0.10) */
959
1014
  interface GetFullTraitVectorInput {
960
1015
  member_id: string;
961
1016
  _payment?: ProvenanceToken;
962
1017
  }
963
- /** (premium L2) get_full_trait_vector output */
1018
+ /** (premium L2) get_full_trait_vector: output */
964
1019
  interface GetFullTraitVectorOutput {
965
1020
  ok: boolean;
966
1021
  member_id: string;
@@ -971,13 +1026,13 @@ interface GetFullTraitVectorOutput {
971
1026
  confidence_interval: [number, number];
972
1027
  }>;
973
1028
  }
974
- /** (premium L4) compute_belonging Compute belonging probability for a person-job pairing ($0.05) */
1029
+ /** (premium L4) compute_belonging: Compute belonging probability for a person-job pairing ($0.60) */
975
1030
  interface ComputeBelongingInput {
976
1031
  member_id: string;
977
1032
  job_id: string;
978
1033
  _payment?: ProvenanceToken;
979
1034
  }
980
- /** (premium L4) compute_belonging output */
1035
+ /** (premium L4) compute_belonging: output */
981
1036
  interface ComputeBelongingOutput {
982
1037
  ok: boolean;
983
1038
  belonging_probability: number;
@@ -988,13 +1043,13 @@ interface ComputeBelongingOutput {
988
1043
  complementarity: number;
989
1044
  };
990
1045
  }
991
- /** (premium L5) get_match_recommendations Get top N match recommendations for a person ($0.50) */
1046
+ /** (premium L5) get_match_recommendations: Get top N match recommendations for a person ($1.00) */
992
1047
  interface GetMatchRecommendationsInput {
993
1048
  member_id: string;
994
1049
  limit?: number;
995
1050
  _payment?: ProvenanceToken;
996
1051
  }
997
- /** (premium L5) get_match_recommendations output */
1052
+ /** (premium L5) get_match_recommendations: output */
998
1053
  interface GetMatchRecommendationsOutput {
999
1054
  ok: boolean;
1000
1055
  recommendations: Array<{
@@ -1008,12 +1063,12 @@ interface GetMatchRecommendationsOutput {
1008
1063
  };
1009
1064
  }>;
1010
1065
  }
1011
- /** (premium L5) generate_match_narrative Generate a human-readable narrative explaining a match ($0.50) */
1066
+ /** (premium L5) generate_match_narrative: Generate a human-readable narrative explaining a match ($1.00) */
1012
1067
  interface GenerateMatchNarrativeInput {
1013
1068
  match_id: string;
1014
1069
  _payment?: ProvenanceToken;
1015
1070
  }
1016
- /** (premium L5) generate_match_narrative output */
1071
+ /** (premium L5) generate_match_narrative: output */
1017
1072
  interface GenerateMatchNarrativeOutput {
1018
1073
  ok: boolean;
1019
1074
  match_id: string;
@@ -1021,14 +1076,14 @@ interface GenerateMatchNarrativeOutput {
1021
1076
  strengths: string[];
1022
1077
  growth_areas: string[];
1023
1078
  }
1024
- /** (premium L2) get_side_quest_graph Get a person's Side Quest Graph (DP noise ε=1.0) ($0.01) */
1079
+ /** (premium L2) get_side_quest_graph: Get a person's Side Quest Graph (DP noise ε=1.0) ($0.10) */
1025
1080
  interface GetSideQuestGraphInput {
1026
1081
  member_id: string;
1027
1082
  include_edges?: boolean;
1028
1083
  min_confidence?: number;
1029
1084
  _payment?: ProvenanceToken;
1030
1085
  }
1031
- /** (premium L2) get_side_quest_graph output */
1086
+ /** (premium L2) get_side_quest_graph: output */
1032
1087
  interface GetSideQuestGraphOutput {
1033
1088
  ok: boolean;
1034
1089
  member_id: string;
@@ -1044,13 +1099,13 @@ interface GetSideQuestGraphOutput {
1044
1099
  }>;
1045
1100
  privacy_epsilon: number;
1046
1101
  }
1047
- /** (premium L3) query_graph_similarity Compare two Side Quest Graphs (DP noise ε=0.5) ($0.025) */
1102
+ /** (premium L3) query_graph_similarity: Compare two Side Quest Graphs (DP noise ε=0.5) ($0.30) */
1048
1103
  interface QueryGraphSimilarityInput {
1049
1104
  member_a_id: string;
1050
1105
  member_b_id: string;
1051
1106
  _payment?: ProvenanceToken;
1052
1107
  }
1053
- /** (premium L3) query_graph_similarity output */
1108
+ /** (premium L3) query_graph_similarity: output */
1054
1109
  interface QueryGraphSimilarityOutput {
1055
1110
  ok: boolean;
1056
1111
  member_a_id: string;
@@ -1060,11 +1115,11 @@ interface QueryGraphSimilarityOutput {
1060
1115
  complementarity: number;
1061
1116
  privacy_epsilon: number;
1062
1117
  }
1063
- /** Free (L0) tool names readonly tuple. Mirrors the live server's `tools/list` free set. */
1118
+ /** Free (L0) tool names: readonly tuple. Mirrors the live server's `tools/list` free set. */
1064
1119
  declare const FREE_TOOL_NAMES: readonly ["hello_agent", "alter_resolve_handle", "list_archetypes", "verify_identity", "initiate_assessment", "get_engagement_level", "get_profile", "query_matches", "get_competencies", "search_identities", "get_identity_earnings", "get_network_stats", "recommend_tool", "get_identity_trust_score", "check_assessment_status", "get_earning_summary", "get_agent_trust_tier", "get_agent_portfolio", "get_privacy_budget", "golden_thread_status", "begin_golden_thread", "complete_knot", "check_golden_thread", "thread_census"];
1065
- /** Premium (x402-gated, L1-L5) tool names readonly tuple. Mirrors the live server's `tools/list` premium set. */
1120
+ /** Premium (x402-gated, L1-L5) tool names: readonly tuple. Mirrors the live server's `tools/list` premium set. */
1066
1121
  declare const PREMIUM_TOOL_NAMES: readonly ["assess_traits", "get_trait_snapshot", "get_full_trait_vector", "compute_belonging", "get_match_recommendations", "generate_match_narrative", "get_side_quest_graph", "query_graph_similarity"];
1067
- /** Union of all 32 tool names */
1122
+ /** Union of all tool names defined in this file (types.ts covers the core set). */
1068
1123
  type ToolName = (typeof FREE_TOOL_NAMES)[number] | (typeof PREMIUM_TOOL_NAMES)[number];
1069
1124
  interface ToolInputs {
1070
1125
  hello_agent: HelloAgentInput;
@@ -1136,23 +1191,23 @@ interface ToolOutputs {
1136
1191
  }
1137
1192
  /**
1138
1193
  * Tool tier mapping (L0=free, L1-L5=paid).
1139
- * Mirrors `TOOL_TIERS` in backend/app/mcp/x402_middleware.py.
1194
+ * Mirrors the live MCP per-invocation tier mapping.
1140
1195
  */
1141
1196
  declare const TOOL_TIERS: Record<ToolName, number>;
1142
1197
  /**
1143
1198
  * Tool price in USD per invocation.
1144
- * Mirrors `TOOL_PRICING` in backend/app/mcp/x402_middleware.py.
1199
+ * Mirrors the live MCP per-invocation pricing.
1145
1200
  * Free tools (L0) are 0.
1146
1201
  */
1147
1202
  declare const TOOL_COSTS: Record<ToolName, number>;
1148
1203
  /**
1149
- * Blast radius classification categorises tools by potential impact.
1150
- * Mirrors `TOOL_BLAST_RADIUS` in backend/app/mcp/x402_middleware.py.
1204
+ * Blast radius classification: categorises tools by potential impact.
1205
+ * Mirrors the live MCP blast-radius classification.
1151
1206
  */
1152
1207
  declare const TOOL_BLAST_RADIUS: Record<ToolName, "low" | "medium" | "high">;
1153
1208
 
1154
1209
  /**
1155
- * AlterClient high-level typed wrapper around the ALTER MCP server.
1210
+ * AlterClient: high-level typed wrapper around the ALTER MCP server.
1156
1211
  *
1157
1212
  * This is the entry point most consumers will use. It bundles
1158
1213
  * {@link MCPClient}, {@link X402Client}, discovery, and provenance
@@ -1186,7 +1241,7 @@ interface AlterClientOptions extends Omit<MCPClientOptions, 'x402'> {
1186
1241
  * to `https://api.truealter.com/.well-known/alter-keys.json`.
1187
1242
  *
1188
1243
  * When set, this URL is used verbatim for every `verifyProvenance`
1189
- * call and *overrides* any `verify_at` hint on the server response
1244
+ * call and *overrides* any `verify_at` hint on the server response:
1190
1245
  * the caller has already vouched for this origin. Must be `https:`.
1191
1246
  */
1192
1247
  jwksUrl?: string;
@@ -1194,7 +1249,7 @@ interface AlterClientOptions extends Omit<MCPClientOptions, 'x402'> {
1194
1249
  * Hostname allowlist applied when resolving an untrusted `verify_at`
1195
1250
  * field on a provenance envelope. Defaults to
1196
1251
  * {@link DEFAULT_VERIFY_AT_ALLOWLIST} (`api.truealter.com`,
1197
- * `mcp.truealter.com`). Passing a list here *replaces* the default
1252
+ * `mcp.truealter.com`). Passing a list here *replaces* the default:
1198
1253
  * include the ALTER canonicals if you still want them accepted.
1199
1254
  *
1200
1255
  * A hostile MCP server can otherwise point `verify_at` at an
@@ -1202,6 +1257,41 @@ interface AlterClientOptions extends Omit<MCPClientOptions, 'x402'> {
1202
1257
  * signing key; the allowlist is the gate that prevents this.
1203
1258
  */
1204
1259
  verifyAtAllowlist?: readonly string[];
1260
+ /**
1261
+ * Skip the D-MIN-VERSION-FLOOR-1 client-side preflight (the lazy
1262
+ * `checkMinVersion()` invocation on first request). Deliberately named
1263
+ * to discourage casual use: the server-side floor gate (Phase 1
1264
+ * middleware) still rejects below-floor clients with HTTP 426
1265
+ * regardless. Disabling the SDK-side preflight only swaps a clean
1266
+ * typed {@link BelowFloorError} for an opaque network error on every
1267
+ * subsequent call.
1268
+ *
1269
+ * Set to `true` only when:
1270
+ * - The SDK is embedded in a non-Node environment without `fs`
1271
+ * access (e.g. Cloudflare Workers) and the disk-cache write fails
1272
+ * loudly. The fetch + in-memory path still works; the warn is
1273
+ * informational only.
1274
+ * - Integration tests that drive the SDK against a local backend
1275
+ * without the floor surface deployed.
1276
+ *
1277
+ * **Server-side version enforcement is NOT skipped by this flag.**
1278
+ */
1279
+ unsafe_skipVersionCheck?: boolean;
1280
+ /**
1281
+ * Override the API base URL used for the
1282
+ * {@link checkMinVersion} preflight. Defaults to the `ALTER_API`
1283
+ * environment variable or `https://api.truealter.com`. Useful for
1284
+ * staging environments and integration tests.
1285
+ */
1286
+ apiBase?: string;
1287
+ /**
1288
+ * Override the known Ed25519 public-key map consulted when verifying
1289
+ * the floor document's signature. Keys are `key_id` (first 8 hex chars
1290
+ * of `SHA-256(raw 32-byte public key)`); values are SPKI-PEM public-key
1291
+ * strings. Defaults to the shipped `KNOWN_FLOOR_PUBLIC_KEYS` map: no
1292
+ * signing secret ships in the client; only public halves.
1293
+ */
1294
+ knownFloorPublicKeys?: Record<string, string>;
1205
1295
  }
1206
1296
  declare class AlterClient {
1207
1297
  readonly mcp: MCPClient;
@@ -1212,18 +1302,18 @@ declare class AlterClient {
1212
1302
  constructor(options?: AlterClientOptions);
1213
1303
  /**
1214
1304
  * Resolve the MCP endpoint via discovery if requested. Safe to call
1215
- * multiple times the first successful lookup is cached.
1305
+ * multiple times: the first successful lookup is cached.
1216
1306
  */
1217
1307
  discoverEndpoint(): Promise<DiscoveryResult>;
1218
1308
  /**
1219
- * Initialise the MCP session. Optional every method calls
1309
+ * Initialise the MCP session. Optional: every method calls
1220
1310
  * `mcp.initialize()` lazily, but you can call this once at startup if
1221
1311
  * you want fail-fast behaviour.
1222
1312
  */
1223
1313
  initialize(): Promise<void>;
1224
- /** First handshake confirms the connection, returns trust tier and tool counts. */
1314
+ /** First handshake: confirms the connection, returns trust tier and tool counts. */
1225
1315
  helloAgent(): Promise<MCPCallToolResult>;
1226
- /** Resolve a ~handle (e.g. ~drew) to its canonical form and kind. No auth required. */
1316
+ /** Resolve a ~handle (e.g. ~example) to its canonical form and kind. No auth required. */
1227
1317
  resolveHandle(args: AlterResolveHandleInput | string): Promise<MCPCallToolResult>;
1228
1318
  /** Verify a person is registered with ALTER (handle or id). */
1229
1319
  verify(handleOrId: string, claims?: VerifyIdentityInput['claims']): Promise<MCPCallToolResult>;
@@ -1297,7 +1387,7 @@ declare class AlterClient {
1297
1387
  /**
1298
1388
  * Verify the ES256 provenance attestation on a tool response.
1299
1389
  * Accepts either a {@link ProvenanceEnvelope} or the raw `_meta`
1300
- * object the latter is more convenient for ad-hoc verification.
1390
+ * object: the latter is more convenient for ad-hoc verification.
1301
1391
  */
1302
1392
  verifyProvenance(envelope: ProvenanceEnvelope | {
1303
1393
  provenance?: ProvenanceEnvelope;
@@ -1323,7 +1413,7 @@ declare class AlterClient {
1323
1413
  * Rules:
1324
1414
  * - object keys are sorted ascending by codepoint
1325
1415
  * - no whitespace
1326
- * - `ensure_ascii=False` non-ASCII characters pass through verbatim
1416
+ * - `ensure_ascii=False`: non-ASCII characters pass through verbatim
1327
1417
  * (not re-encoded as \\uXXXX). UTF-8 encoding happens at the byte
1328
1418
  * layer before hashing.
1329
1419
  *
@@ -1347,7 +1437,7 @@ declare function canonicalArgsSha256(toolArgs: Record<string, unknown>): string;
1347
1437
  */
1348
1438
  declare function loadPrivateKey(key: Uint8Array | string): Uint8Array;
1349
1439
  interface InvocationClaims {
1350
- /** Tool name must equal the `tools/call` `params.name`. */
1440
+ /** Tool name: must equal the `tools/call` `params.name`. */
1351
1441
  tool: string;
1352
1442
  /** Hex SHA-256 of canonical-JSON `tool_args`. */
1353
1443
  args_sha256: string;
@@ -1386,6 +1476,249 @@ interface SignInvocationOptions {
1386
1476
  */
1387
1477
  declare function signInvocation(toolName: string, toolArgs: Record<string, unknown>, options: SignInvocationOptions): string;
1388
1478
 
1479
+ /**
1480
+ * floor-preflight: SDK-side D-MIN-VERSION-FLOOR-1 Phase 4 enforcement.
1481
+ *
1482
+ * Sister to `alter-cli`'s `src/lib/floor-preflight.ts` (Phase 2). This is
1483
+ * the `@truealter/sdk` implementation: it fires lazily on the first
1484
+ * authenticated network call from {@link AlterClient}, hits the public
1485
+ * floor endpoint, verifies the Ed25519 signature against the published
1486
+ * `key_id`, and throws {@link BelowFloorError} when the SDK's own
1487
+ * version is below the published floor for `alter-identity`.
1488
+ *
1489
+ * Canonical envelope (§4) is preserved on the thrown error so consumers
1490
+ * can introspect the upgrade path:
1491
+ *
1492
+ * - `client_version`
1493
+ * - `min_version`
1494
+ * - `upgrade_cmd`
1495
+ * - `channel`
1496
+ * - `message`
1497
+ *
1498
+ * The server-side gate (Phase 1 middleware) is the authoritative reject.
1499
+ * This SDK-side preflight is UX polish: third-party integrators see a
1500
+ * clean typed error before the network call, not an opaque HTTP 426
1501
+ * wall on every subsequent request.
1502
+ *
1503
+ * Ed25519 signature verification (§A3 + §A18): the server signs the floor
1504
+ * document with a floor-only Ed25519 private key. The SDK ships only the
1505
+ * corresponding public key (SPKI PEM) in {@link KNOWN_FLOOR_PUBLIC_KEYS},
1506
+ * keyed by `key_id`. No signing secret ships in the client: this is
1507
+ * asymmetric: the public key cannot forge signatures. MUST stay
1508
+ * byte-compatible with `backend/app/core/floor_signing.py` and the
1509
+ * canonical TypeScript client (`alter-cli` `src/lib/floor-preflight.ts`):
1510
+ * - Algorithm: Ed25519 (RFC 8032). Deterministic: same key + payload
1511
+ * always yields the same signature.
1512
+ * - `key_id` = first 8 hex chars of SHA-256(raw 32-byte public key).
1513
+ * - Payload = `canonicalJson({floors, served_at})`: sorted keys at
1514
+ * every depth, compact separators, raw UTF-8 (the backend's
1515
+ * `ensure_ascii=False` parity is REQUIRED).
1516
+ * `cache_ttl_seconds`, `signature`, `key_id` are excluded
1517
+ * from the signed bytes.
1518
+ * - `signature` = hex-encoded 64-byte Ed25519 signature (128 hex chars).
1519
+ *
1520
+ * Connectivity ladder (§8 + §9):
1521
+ * - In-memory cache fresh (≤ server-advised TTL, clamped [60s, 24h]):
1522
+ * trust the cached floor; no refetch.
1523
+ * - Disk cache ≤24h: trust; permit operation.
1524
+ * - Disk cache 24h-7d: permit with warn.
1525
+ * - Disk cache >7d + backend unreachable: permit with warn.
1526
+ * - Below-floor + backend unreachable: BLOCK. The only intentional
1527
+ * offline lockout: the user had time to upgrade and didn't.
1528
+ */
1529
+ declare const MIN_VERSION_ENDPOINT = "/v1/clients/min-version";
1530
+ /** Client-id surface for the SDK: matches the floor doc's `alter-identity` key. */
1531
+ declare const CLIENT_ID = "alter-identity";
1532
+ /** Channel: SDK installs are always via npm. */
1533
+ declare const CLIENT_CHANNEL = "npm";
1534
+ /**
1535
+ * Compute the 8-char `key_id` for an Ed25519 public key (SPKI PEM).
1536
+ *
1537
+ * Matches the backend `key_id_for_public_key(pub)` in
1538
+ * `backend/app/core/floor_signing.py`:
1539
+ * raw = pub.public_bytes(Encoding.Raw, PublicFormat.Raw) # 32 bytes
1540
+ * sha256(raw).hexdigest()[:8]
1541
+ *
1542
+ * Node equivalent: import PEM -> export JWK -> decode `.x` (base64url) -> 32-byte
1543
+ * raw public key -> SHA-256 -> first 8 hex chars.
1544
+ *
1545
+ * Returns `"00000000"` for empty input (sentinel, matches Phase 1 parity).
1546
+ */
1547
+ declare function computeKeyId(publicKeyPem: string): string;
1548
+ /**
1549
+ * Canonical JSON encoding matching Python's
1550
+ * `json.dumps(obj, sort_keys=True, separators=(",", ":"), ensure_ascii=False)`.
1551
+ * Object keys are sorted lexicographically AT EVERY DEPTH; whitespace is
1552
+ * stripped via the `,`/`:` separators; non-ASCII passes through as raw UTF-8
1553
+ * (Node's `JSON.stringify` never `\uXXXX`-escapes non-ASCII, matching the
1554
+ * backend's `ensure_ascii=False`). The result is the byte-exact input to
1555
+ * Ed25519 signing (backend) and verification (this SDK and alter-cli) on
1556
+ * both sides.
1557
+ */
1558
+ declare function canonicalJson(obj: unknown): string;
1559
+ /**
1560
+ * Known Ed25519 public keys (SPKI PEM) keyed by `key_id`.
1561
+ *
1562
+ * `key_id` = first 8 hex chars of SHA-256(raw 32-byte Ed25519 public key).
1563
+ * Use `computeKeyId(spkiPem)` to re-derive and validate the map key.
1564
+ *
1565
+ * Backend may rotate via D-MSG11 dual-key path: clients keep N keys and
1566
+ * select via `key_id`. Add new keys additively; remove old keys only after
1567
+ * all deployed clients have received the new key.
1568
+ *
1569
+ * Current keys (mirrors `KNOWN_FLOOR_PUBLIC_KEYS` in the canonical
1570
+ * `alter-cli` client):
1571
+ * 8aa59e05: dev/non-prod key (local + e2e + staging). Safe to ship publicly;
1572
+ * this is the PUBLIC key only, never the private key.
1573
+ * 640f7d9a: prod key. Added 2026-06-05. key_id = first 8 hex of
1574
+ * SHA-256(raw 32-byte Ed25519 pubkey), verified against the live
1575
+ * /api/v1/clients/min-version response on 2026-06-05. The prod
1576
+ * private key is a deliberately-minted Fly-secret keypair; only
1577
+ * the public half is shipped here.
1578
+ *
1579
+ * Consumers can override via {@link CheckMinVersionOptions.knownFloorPublicKeys}
1580
+ * for tests or staging environments with a non-default keypair.
1581
+ */
1582
+ declare const KNOWN_FLOOR_PUBLIC_KEYS: Record<string, string>;
1583
+ /**
1584
+ * The canonical `client_below_floor` envelope shape. Identical across
1585
+ * HTTP 426, MCP `tools/call` error, WebSocket close-4426 reason, and the
1586
+ * CLI stdout JSON path. `BelowFloorError` preserves every field as
1587
+ * an enumerable property so consumers can introspect without parsing the
1588
+ * `cause` chain.
1589
+ */
1590
+ interface ClientBelowFloorEnvelope {
1591
+ error: {
1592
+ code: 'client_below_floor';
1593
+ message: string;
1594
+ client_version: string;
1595
+ min_version: string;
1596
+ upgrade_cmd: string;
1597
+ channel: string;
1598
+ };
1599
+ }
1600
+ interface ChannelFloor {
1601
+ min_version: string;
1602
+ upgrade_cmd: string;
1603
+ }
1604
+ interface FloorDocument {
1605
+ floors: Record<string, ChannelFloor | Record<string, ChannelFloor>>;
1606
+ served_at: string;
1607
+ cache_ttl_seconds: number;
1608
+ signature: string;
1609
+ key_id: string;
1610
+ }
1611
+ interface CheckMinVersionOptions {
1612
+ /** API base. Defaults to `ALTER_API` env var, else `https://api.truealter.com`. */
1613
+ apiBase?: string;
1614
+ /** Override the SDK's own version (tests). */
1615
+ clientVersion?: string;
1616
+ /** Override the client-id surface (tests). */
1617
+ clientId?: string;
1618
+ /** Override the channel (tests). */
1619
+ channel?: string;
1620
+ /**
1621
+ * Override the `key_id -> SPKI-PEM` Ed25519 public-key map consulted
1622
+ * when verifying the floor document's signature. Defaults to
1623
+ * {@link KNOWN_FLOOR_PUBLIC_KEYS}.
1624
+ */
1625
+ knownFloorPublicKeys?: Record<string, string>;
1626
+ /** Override fetch: defaults to global `fetch`. */
1627
+ fetchImpl?: typeof fetch;
1628
+ /** Disk cache path override (tests). Set `null` to disable disk cache. */
1629
+ diskCachePath?: string | null;
1630
+ /** Internal: clock injection for tests. */
1631
+ now?: () => number;
1632
+ }
1633
+ /**
1634
+ * Outcome of a preflight check. Use `BelowFloorError` instead of
1635
+ * inspecting this manually: `checkMinVersion()` throws on below-floor.
1636
+ */
1637
+ interface PreflightResult {
1638
+ ok: true;
1639
+ /** Resolved floor for `(client_id, channel)`, when one exists. */
1640
+ floor: ChannelFloor | null;
1641
+ /** Warning emitted when cache is stale or fetch failed. */
1642
+ warn?: string;
1643
+ /** Diagnostic tag: which branch of the ladder fired. */
1644
+ diagnostic: string;
1645
+ }
1646
+ /**
1647
+ * Thrown by {@link checkMinVersion} (and consequently by every
1648
+ * `AlterClient` method, on first request) when the running SDK version
1649
+ * is below the published floor for `alter-identity`.
1650
+ *
1651
+ * The canonical envelope shape is preserved as enumerable properties so
1652
+ * consumers can branch on the upgrade command without re-parsing the
1653
+ * server response:
1654
+ *
1655
+ * ```ts
1656
+ * try {
1657
+ * await client.helloAgent();
1658
+ * } catch (err) {
1659
+ * if (err instanceof BelowFloorError) {
1660
+ * console.error(`upgrade required: ${err.upgrade_cmd}`);
1661
+ * process.exit(1);
1662
+ * }
1663
+ * throw err;
1664
+ * }
1665
+ * ```
1666
+ *
1667
+ * The server-side gate is the authoritative reject: even if a consumer
1668
+ * catches and swallows this error, the next backend request will still
1669
+ * receive HTTP 426 from the floor middleware.
1670
+ */
1671
+ declare class BelowFloorError extends Error {
1672
+ readonly name = "BelowFloorError";
1673
+ readonly code: "client_below_floor";
1674
+ readonly client_version: string;
1675
+ readonly min_version: string;
1676
+ readonly upgrade_cmd: string;
1677
+ readonly channel: string;
1678
+ readonly envelope: ClientBelowFloorEnvelope;
1679
+ constructor(envelope: ClientBelowFloorEnvelope);
1680
+ }
1681
+ /**
1682
+ * Preflight the floor endpoint and compare the SDK's version against
1683
+ * the published `min_version` for `alter-identity`. Throws
1684
+ * {@link BelowFloorError} on below-floor; resolves with a
1685
+ * {@link PreflightResult} otherwise.
1686
+ *
1687
+ * Cache behaviour:
1688
+ * - In-memory cache is consulted first; hits avoid the network.
1689
+ * - On a miss, the disk cache (`~/.config/alter/floor-cache.json`) is
1690
+ * read. If it's <24h old it satisfies the request directly; older
1691
+ * entries trigger a refetch.
1692
+ * - On a successful fetch, both caches are populated.
1693
+ * - On a fetch failure with a stale-but-present disk cache, the
1694
+ * cached verdict bites (including blocking when below-floor: §9).
1695
+ * - On a fetch failure with no cache at all, the call permits with a
1696
+ * warn: the server-side gate catches below-floor regardless.
1697
+ */
1698
+ declare function checkMinVersion(opts?: CheckMinVersionOptions): Promise<PreflightResult>;
1699
+ /**
1700
+ * Strict semver compare. Returns <0 if a<b, 0 if equal, >0 if a>b.
1701
+ * Pre-release tags sort before their release counterpart per semver.
1702
+ */
1703
+ declare function compareSemver(a: string, b: string): number;
1704
+ /**
1705
+ * Verify the floor document's Ed25519 signature. Returns true on valid sig,
1706
+ * false on invalid signature or unknown `key_id`. The signed payload is the
1707
+ * canonical JSON of `{ floors, served_at }`: `signature` + `key_id` +
1708
+ * `cache_ttl_seconds` are excluded from the signed bytes.
1709
+ *
1710
+ * MUST stay byte-compatible with the backend (`backend/app/core/floor_signing.py`):
1711
+ * - Algorithm: Ed25519 (RFC 8032). Deterministic: same key + payload = same sig.
1712
+ * - Payload: `canonicalJson({floors, served_at})`: sorted-keys + compact.
1713
+ * - `key_id`: first 8 hex chars of SHA-256(raw 32-byte Ed25519 public key).
1714
+ * - `signature`: hex-encoded 64-byte Ed25519 signature.
1715
+ *
1716
+ * The `keys` parameter maps `key_id -> SPKI PEM string`; defaults to
1717
+ * `KNOWN_FLOOR_PUBLIC_KEYS`. Returns false on unknown key_id (triggers refetch
1718
+ * per D-MSG11 rotation path).
1719
+ */
1720
+ declare function verifyFloorSignature(doc: FloorDocument, keys?: Record<string, string>): boolean;
1721
+
1389
1722
  interface McpServerConfig {
1390
1723
  url: string;
1391
1724
  transport: 'streamable-http';
@@ -1432,7 +1765,7 @@ declare function generateCursorConfig(opts?: GenerateMcpConfigOptions): GenericM
1432
1765
  /**
1433
1766
  * Claude Desktop MCP config helper.
1434
1767
  *
1435
- * Claude Desktop speaks stdio only it does not currently dial
1768
+ * Claude Desktop speaks stdio only: it does not currently dial
1436
1769
  * Streamable-HTTP MCP servers directly. The canonical bridge is our
1437
1770
  * own `alter-mcp-bridge` binary, which is published alongside this CLI
1438
1771
  * in the same npm package. Desktop hosts then spawn the bridge as a
@@ -1491,7 +1824,7 @@ declare const ALL_CLIENTS: readonly ClientPaths[];
1491
1824
  * - claude-desktop: platform config directory exists
1492
1825
  * - vscode : VS Code user data directory exists
1493
1826
  *
1494
- * The probe is deliberately permissive "the config directory exists"
1827
+ * The probe is deliberately permissive: "the config directory exists"
1495
1828
  * means either the app is installed or was recently installed. Wire
1496
1829
  * will still refuse if the config file ends up on a synced volume.
1497
1830
  */
@@ -1499,9 +1832,9 @@ declare const ALL_CLIENTS: readonly ClientPaths[];
1499
1832
  interface ProbeResult {
1500
1833
  client: ClientPaths;
1501
1834
  installed: boolean;
1502
- /** Only present for claude-code records `claude --version` output when resolvable. */
1835
+ /** Only present for claude-code: records `claude --version` output when resolvable. */
1503
1836
  version?: string;
1504
- /** Diagnostic trail why we said installed/not. */
1837
+ /** Diagnostic trail: why we said installed/not. */
1505
1838
  reason: string;
1506
1839
  }
1507
1840
  declare function probeClaudeCode(): ProbeResult;
@@ -1517,7 +1850,7 @@ declare function probeAll(): ProbeResult[];
1517
1850
  * post) to make the operation auditable.
1518
1851
  *
1519
1852
  * Append-only semantics: a new wire run rewrites this file in full.
1520
- * Prior state is not retained the backup siblings on disk are the
1853
+ * Prior state is not retained: the backup siblings on disk are the
1521
1854
  * canonical rollback surface, not this file.
1522
1855
  */
1523
1856
 
@@ -1561,7 +1894,7 @@ declare function writeWireState(state: WireState): void;
1561
1894
  * Writing MCP config under iCloud / OneDrive / Dropbox / Google Drive
1562
1895
  * silently propagates the same `mcpServers.alter` entry (and API key
1563
1896
  * headers) to every other device the user syncs. That is a consent
1564
- * violation wire consent is per-device.
1897
+ * violation: wire consent is per-device.
1565
1898
  *
1566
1899
  * The check is a prefix match against the resolved absolute path; it
1567
1900
  * is deliberately broader than strictly necessary so that users who
@@ -1591,15 +1924,21 @@ declare function sha256(bytes: string | Buffer): string;
1591
1924
  * structured report. `unwire()` reads that artefact and reverses
1592
1925
  * every target.
1593
1926
  *
1594
- * Synchronous throughout the CLI path is sequential and the
1927
+ * Synchronous throughout: the CLI path is sequential and the
1595
1928
  * deterministic ordering is worth the tiny blocking cost.
1596
1929
  */
1597
1930
 
1931
+ interface CfAccessCredentials {
1932
+ clientId: string;
1933
+ clientSecret: string;
1934
+ }
1598
1935
  interface WireOptions {
1599
1936
  /** Override the endpoint written into every client config. Defaults to DEFAULT_ENDPOINT. */
1600
1937
  endpoint?: string;
1601
1938
  /** Optional API key written into `headers['X-ALTER-API-Key']` for each target. */
1602
1939
  apiKey?: string;
1940
+ /** CF Access service token credentials. Auto-read from ~/.config/alter/cf-access.env when absent. */
1941
+ cfAccess?: CfAccessCredentials;
1603
1942
  /** Restrict to a subset of client ids. Default: every detected client. */
1604
1943
  only?: readonly ClientId[];
1605
1944
  /** Skip any client whose probe said "not installed" even if the caller passed it via `only`. */
@@ -1621,18 +1960,52 @@ interface UnwireReport {
1621
1960
  declare function unwire(): UnwireReport;
1622
1961
 
1623
1962
  /**
1624
- * @truealter/sdk alter_homepage MCP tool types
1963
+ * GENERATED: DO NOT EDIT BY HAND. The SDK's compiled mirror of ALTER's live
1964
+ * MCP pricing surface: advertised tool counts, per-invocation tiers, and
1965
+ * per-invocation pricing.
1966
+ *
1967
+ * Regenerate via the SDK freshness gate. A freshness check runs at publish
1968
+ * time and fails if this file diverges from the live pricing surface.
1969
+ *
1970
+ * Canonical source of truth for x402 pricing and advertised tool counts inside
1971
+ * the SDK. Consumers should import from "@truealter/sdk" (re-exported via
1972
+ * index.ts), not from this module directly.
1973
+ */
1974
+ /** Tool tier per invocation (0=free / L0, 1=L1, 2=L2, 3=L3, 4=L4, 5=L5). */
1975
+ declare const GENERATED_TOOL_TIERS: Record<string, number>;
1976
+ /** Price in USD per tool invocation. Mirrors the live MCP pricing surface. */
1977
+ declare const GENERATED_TOOL_PRICING: Record<string, number>;
1978
+ /** Flat price per tier in USD. L0 is always free. */
1979
+ declare const TIER_PRICES: Record<string, number>;
1980
+ /** Publicly advertised tool counts. Mirrors canonical-facts.json public_advertised. */
1981
+ declare const ADVERTISED_TOOL_COUNTS: {
1982
+ /** Free (L0) tools visible to anonymous / agent-class callers. */
1983
+ readonly free: 26;
1984
+ /** Premium (L1-L5) tools requiring x402 payment. */
1985
+ readonly premium: 8;
1986
+ /** Messaging tools (member-self-only; excluded from external advertisement). */
1987
+ readonly messaging: 0;
1988
+ /** Total publicly advertised (free + premium). */
1989
+ readonly total: 34;
1990
+ };
1991
+ /** x402 settlement revenue split. Weaver = the data subject earning Identity Income. */
1992
+ declare const REVENUE_SPLIT: {
1993
+ readonly weaver: 0.75;
1994
+ readonly facilitator: 0.05;
1995
+ readonly alter: 0.15;
1996
+ readonly treasury: 0.05;
1997
+ };
1998
+
1999
+ /**
2000
+ * @truealter/sdk: alter_homepage MCP tool types
1625
2001
  *
1626
2002
  * Wire-format types for the user-authored, externally-queryable identity
1627
- * homepage surface ratified (proposed) as D-CUST-PORTFOLIO-1 in
1628
- * alter-internal Session 54.
2003
+ * homepage surface.
1629
2004
  *
1630
- * Tool name note: ratified-as `alter_portfolio` in the proposed DR;
1631
- * shipping as `alter_homepage` because `alter_portfolio` is already
1632
- * taken by the verified-attestations tool in mcp-alter (different
1633
- * concept). Per the handover's explicit fallback. The DR text and
1634
- * companion docs may still say "portfolio" — the wire-format and
1635
- * tool-name-on-server are `homepage`.
2005
+ * Tool name note: the wire-format and server-side tool name are
2006
+ * `alter_homepage`. The name `alter_portfolio` is reserved by the
2007
+ * verified-attestations tool in `mcp-alter` (a different concept), so
2008
+ * homepage types ship under `homepage`.
1636
2009
  *
1637
2010
  * Wire-format rule: every field name matches the JSON Schema property
1638
2011
  * name exactly (snake_case). These are passed straight into JSON-RPC
@@ -1652,7 +2025,7 @@ type HomepageFieldProvenance = "declared" | "derived" | "attested";
1652
2025
  /**
1653
2026
  * One field of a HomepageManifest. Every field carries its provenance
1654
2027
  * class so MCP consumers can render appropriately. The `value` shape is
1655
- * field-specific this is a discriminated parent; consumers should
2028
+ * field-specific: this is a discriminated parent; consumers should
1656
2029
  * narrow on the manifest's field name, not on `value`'s runtime shape.
1657
2030
  */
1658
2031
  interface HomepageField<T = unknown> {
@@ -1669,7 +2042,7 @@ interface HomepageField<T = unknown> {
1669
2042
  /**
1670
2043
  * The wire-format manifest returned by `alter_homepage(handle)`.
1671
2044
  *
1672
- * Fields are individually optional a HomepageManifest with only a
2045
+ * Fields are individually optional: a HomepageManifest with only a
1673
2046
  * handle and an opener is valid. MCP consumers MUST NOT assume any
1674
2047
  * field other than `handle` is present.
1675
2048
  */
@@ -1690,15 +2063,25 @@ interface HomepageManifest {
1690
2063
  */
1691
2064
  opener?: HomepageField<string>;
1692
2065
  /**
1693
- * Composed-glyph string (from typed primitives, D-CUST-1 M3). The
1694
- * sigil is a string of renderer-recognised primitive references
1695
- * not raw glyph codes so different consumers can render the same
2066
+ * Composed-glyph string (from typed primitives). The
2067
+ * sigil is a string of renderer-recognised primitive references:
2068
+ * not raw glyph codes: so different consumers can render the same
1696
2069
  * sigil distinctly. Provenance is `declared` for user-composed,
1697
2070
  * `derived` for sigil-from-thread-graph crystallisation.
1698
2071
  */
1699
2072
  sigil?: HomepageField<string>;
1700
2073
  /** User's pronouns (already-shipped surface). Always declared. */
1701
2074
  pronouns?: HomepageField<string>;
2075
+ /**
2076
+ * User-authored contact email, surfaced so a verified caller reading
2077
+ * the homepage can reach the holder. Maximum 254 chars (RFC 5321
2078
+ * envelope limit) after NFC normalisation. Always declared-provenance
2079
+ *: the user wrote it into their config; it is NOT the account's
2080
+ * verified login email (that lives encrypted server-side and is never
2081
+ * surfaced here). A holder who sets no `contact_email` simply omits
2082
+ * the field.
2083
+ */
2084
+ contact_email?: HomepageField<string>;
1702
2085
  /**
1703
2086
  * List of recognised Seat glyphs the holder is bound to. Provenance
1704
2087
  * is always `attested` (ceremony-attested, server-side resolved);
@@ -1716,7 +2099,7 @@ interface HomepageManifest {
1716
2099
  /**
1717
2100
  * Optional, opt-in per query context. Coarse Golden-Thread summary;
1718
2101
  * provenance is `derived`. MCP consumers MUST NOT request this field
1719
- * by default only on explicit per-call consent. Consumers in the
2102
+ * by default: only on explicit per-call consent. Consumers in the
1720
2103
  * workplace/education vertical MUST NOT request this field at all
1721
2104
  * (clause-4 caller-context gate).
1722
2105
  */
@@ -1726,6 +2109,14 @@ interface HomepageManifest {
1726
2109
  * Consumers are free to ignore. Provenance is always `declared`.
1727
2110
  */
1728
2111
  render_hints?: HomepageField<Record<string, unknown>>;
2112
+ /**
2113
+ * Reserved inner-face slot. NEVER populated on a HomepageManifest returned
2114
+ * by `alter_homepage`: the homepage is the outward-facing identity surface,
2115
+ * and the inside face is held empty by construction. The field exists only
2116
+ * so consumers and forward-compatible schemas can name the slot; a manifest
2117
+ * carrying a value here is malformed and consumers MUST ignore it.
2118
+ */
2119
+ reserved_inner?: never;
1729
2120
  }
1730
2121
  /**
1731
2122
  * Input arguments for the `alter_homepage` MCP tool.
@@ -1740,7 +2131,7 @@ interface HomepageInput {
1740
2131
  /**
1741
2132
  * Optional whitelist of field names. If omitted, the server returns
1742
2133
  * all fields the caller is permitted to read. Unknown field names
1743
- * are silently ignored (forward-compatible adding a new field does
2134
+ * are silently ignored (forward-compatible: adding a new field does
1744
2135
  * not break old consumers).
1745
2136
  */
1746
2137
  fields?: readonly (keyof HomepageManifest)[];
@@ -1774,23 +2165,21 @@ interface HomepageOutput {
1774
2165
  type HomepageCallerVertical = "workplace" | "education" | "personal" | "civic" | "agent" | "unknown";
1775
2166
  /** Maximum sizes from the spec. SDK consumers can use these to validate
1776
2167
  * input before sending. Mirrored from
1777
- * `docs/technical/alter-portfolio-manifest-v1.md` (forthcoming) and
1778
- * the proposed-D-CUST-PORTFOLIO-1 DR. */
2168
+ * `docs/technical/alter-portfolio-manifest-v1.md` (forthcoming). */
1779
2169
  declare const HOMEPAGE_LIMITS: {
1780
2170
  readonly whoami_max_chars: 240;
1781
2171
  readonly opener_max_chars: 280;
1782
2172
  readonly pronouns_max_chars: 32;
1783
2173
  readonly attunement_glyph_max_chars: 16;
2174
+ readonly contact_email_max_chars: 254;
1784
2175
  };
1785
2176
 
1786
2177
  /**
1787
- * @truealter/sdk theme pack types (D-CUST-1 substrate, Wave 2)
2178
+ * @truealter/sdk: theme pack types
1788
2179
  *
1789
2180
  * Wire-format types for ALTER theme packs and `themes.lock` composition
1790
2181
  * manifests. The full specification lives in
1791
- * `docs/technical/alter-theme-pack-spec-v1.md`; the architecture spike
1792
- * (with threat model F1–F10) lives in
1793
- * `.repos/internal/02-Technical-Strategy/alter-theme-packs-architecture-spike.md`.
2182
+ * `docs/technical/alter-theme-pack-spec-v1.md`.
1794
2183
  *
1795
2184
  * These types describe the on-the-wire shape of theme manifests as they
1796
2185
  * are produced by `alter theme install`, persisted to `themes.lock`,
@@ -1820,9 +2209,9 @@ interface ThemeMeta {
1820
2209
  author: string;
1821
2210
  /** ≤ 240 characters after NFC. */
1822
2211
  description: string;
1823
- /** OPTIONAL surfaced by curated resolvers; not rendered by ALTER. */
2212
+ /** OPTIONAL: surfaced by curated resolvers; not rendered by ALTER. */
1824
2213
  repo?: string;
1825
- /** OPTIONAL surfaced by curated resolvers; not rendered by ALTER. */
2214
+ /** OPTIONAL: surfaced by curated resolvers; not rendered by ALTER. */
1826
2215
  docs_url?: string;
1827
2216
  }
1828
2217
  /** `[palette]` section. Renderer enforces gamut; out-of-gamut packs are rejected. */
@@ -1856,7 +2245,7 @@ interface ThemeRenderHints {
1856
2245
  }
1857
2246
  /** `[assets]` section. Paths MUST be repo-relative without `..` segments. */
1858
2247
  interface ThemeAssets {
1859
- /** Optional if omitted, no assets are loaded. */
2248
+ /** Optional: if omitted, no assets are loaded. */
1860
2249
  glyphs?: readonly string[];
1861
2250
  }
1862
2251
  /**
@@ -1906,7 +2295,7 @@ interface ThemeLockEntry {
1906
2295
  }
1907
2296
  /**
1908
2297
  * The user-side composition manifest. This is the publishable artefact
1909
- * what someone shares when they say "here is my ALTER".
2298
+ *: what someone shares when they say "here is my ALTER".
1910
2299
  *
1911
2300
  * Re-applying the same lockfile against the same renderer version MUST
1912
2301
  * produce a bit-identical render, modulo the `attunement_glyph` field
@@ -1914,7 +2303,7 @@ interface ThemeLockEntry {
1914
2303
  */
1915
2304
  interface ThemesLockV1 {
1916
2305
  schema_version: 1;
1917
- /** e.g. "alter-cli/0.5.0" informational, not load-bearing. */
2306
+ /** e.g. "alter-cli/0.5.0", informational only. */
1918
2307
  generated_by: string;
1919
2308
  /** RFC 3339 UTC timestamp at lockfile-write time. */
1920
2309
  generated_at: string;
@@ -1930,7 +2319,7 @@ interface ThemesLockV1 {
1930
2319
  * Input arguments for the `theme_share` MCP tool. Sharing emits a 5:1
1931
2320
  * return event to the sharer (recognition credit + pack citation) and
1932
2321
  * to the recipient (discovery signal). Implementation lives in
1933
- * `mcp-alter` per D-RS15.
2322
+ * `mcp-alter`.
1934
2323
  */
1935
2324
  interface ThemeShareInput {
1936
2325
  /** Recipient ~handle. */
@@ -1966,11 +2355,11 @@ declare const OSC8_ALLOWED_SCHEMES: readonly ["https:", "mailto:"];
1966
2355
  type Osc8AllowedScheme = (typeof OSC8_ALLOWED_SCHEMES)[number];
1967
2356
 
1968
2357
  /**
1969
- * Package metadata kept in a standalone module so deep imports from
2358
+ * Package metadata: kept in a standalone module so deep imports from
1970
2359
  * `src/wire/` can reference version constants without creating a
1971
2360
  * circular dependency through `src/index.ts`.
1972
2361
  */
1973
2362
  declare const SDK_NAME = "@truealter/sdk";
1974
- declare const SDK_VERSION = "0.3.0";
2363
+ declare const SDK_VERSION: string;
1975
2364
 
1976
- export { ALL_CLIENTS, AlterAuthError, AlterClient, type AlterClientOptions, AlterDiscoveryError, AlterError, type AlterErrorCode, AlterInvalidResponse, AlterNetworkError, AlterPaymentRequired, AlterProvenanceError, AlterRateLimited, type AlterResolveHandleInput, type AlterResolveHandleOutput, AlterTimeoutError, AlterToolError, type ApiKeyConfig, type Archetype, type AssessTraitsInput, type AssessTraitsOutput, type BeginGoldenThreadInput, type BeginGoldenThreadOutput, CLAUDE_CODE, CLAUDE_DESKTOP, CURSOR, type CheckAssessmentStatusInput, type CheckAssessmentStatusOutput, type CheckGoldenThreadInput, type CheckGoldenThreadOutput, type ClaudeDesktopConfig, type ClaudeDesktopServerConfig, type ClientId, type ClientPaths, type CompleteKnotInput, type CompleteKnotOutput, type ComputeBelongingInput, type ComputeBelongingOutput, DEFAULT_DOMAIN, DEFAULT_ENDPOINT, DEFAULT_VERIFY_AT_ALLOWLIST, type DiscoveryOptions, type DiscoveryResult, type Ed25519Keypair, type EngagementLevel, FREE_TOOL_NAMES, type GenerateClaudeDesktopOptions, type GenerateMatchNarrativeInput, type GenerateMatchNarrativeOutput, type GetAgentPortfolioInput, type GetAgentPortfolioOutput, type GetAgentTrustTierInput, type GetAgentTrustTierOutput, type GetCompetenciesInput, type GetCompetenciesOutput, type GetEarningSummaryInput, type GetEarningSummaryOutput, type GetEngagementLevelInput, type GetEngagementLevelOutput, type GetFullTraitVectorInput, type GetFullTraitVectorOutput, type GetIdentityEarningsInput, type GetIdentityEarningsOutput, type GetIdentityTrustScoreInput, type GetIdentityTrustScoreOutput, type GetMatchRecommendationsInput, type GetMatchRecommendationsOutput, type GetNetworkStatsInput, type GetNetworkStatsOutput, type GetPrivacyBudgetInput, type GetPrivacyBudgetOutput, type GetProfileInput, type GetProfileOutput, type GetSideQuestGraphInput, type GetSideQuestGraphOutput, type GetTraitSnapshotInput, type GetTraitSnapshotOutput, type GoldenThreadStatusInput, type GoldenThreadStatusOutput, type GreetingRegister, HOMEPAGE_LIMITS, type HelloAgentInput, type HelloAgentOutput, type HomepageCallerVertical, type HomepageField, type HomepageFieldProvenance, type HomepageInput, type HomepageManifest, type HomepageOutput, type InitiateAssessmentInput, type InitiateAssessmentOutput, type InvocationClaims, type JsonWebKey, type JwksDocument, type ListArchetypesInput, type ListArchetypesOutput, type MCPCallOptions, type MCPCallToolResult, MCPClient, type MCPClientInfo, type MCPClientOptions, type MCPContentBlock, type MCPListToolsResult, type MCPMeta, type MCPResponse, type MCPSigningOptions, type MCPToolDefinition, MCP_PROTOCOL_VERSION, type MatchTier, type McpServerConfig, OSC8_ALLOWED_SCHEMES, type Osc8AllowedScheme, PREMIUM_TOOL_NAMES, type PaletteFloorV1, type PaletteText, type PanelDensity, type PaymentEnvelope, type ProbeResult, type ProvenanceEnvelope, type ProvenancePayload, type ProvenanceToken, type ProvenanceVerification, type QueryGraphSimilarityInput, type QueryGraphSimilarityOutput, type QueryMatchesInput, type QueryMatchesOutput, type RecommendToolInput, type RecommendToolOutput, SDK_NAME, SDK_VERSION, type SearchIdentitiesInput, type SearchIdentitiesOutput, type SignInvocationOptions, type SignedToolDefinition, type StatusLineDensity, type StatusLineSlot, THEME_LIMITS, TOOL_BLAST_RADIUS, TOOL_COSTS, TOOL_TIERS, type ThemeAssets, type ThemeLockEntry, type ThemeManifestV1, type ThemeMeta, type ThemeOpener, type ThemePalette, type ThemeRenderHints, type ThemeShareInput, type ThemeShareOutput, type ThemeSigil, type ThemeSignatureManifest, type ThemeStatusLine, type ThemesLockV1, type ThreadCensusInput, type ThreadCensusOutput, type ToolInputs, type ToolName, type ToolOutputs, type ToolSignatureMap, type UnwireReport, VSCODE, type VerifyIdentityInput, type VerifyIdentityOutput, type VerifyProvenanceOptions, type WireOptions, type WireReport, type WireState, type WireTarget, type WireTargetCli, type WireTargetFile, X402Client, type X402ClientOptions, type X402Settlement, type X402Signer, base64urlDecode, base64urlEncode, canonicalArgsSha256, canonicalStringify, clearDiscoveryCache, decodeDid, detectSyncedVolume, discover, encodeDid, fetchPublicKeys, generateClaudeConfig, generateClaudeDesktopConfig, generateCursorConfig, generateGenericMcpConfig, generateKeypair, keypairFromPrivateKey, loadPrivateKey, parsePaymentHeader, probeAll, probeByDir, probeClaudeCode, readWireState, resolveVerifyAt, sha256, sign, signInvocation, unwire, verify, verifyProvenance, verifyToolSignatures, wire, writeWireState };
2365
+ export { ADVERTISED_TOOL_COUNTS, ALL_CLIENTS, AlterAuthError, AlterClient, type AlterClientOptions, AlterDiscoveryError, AlterError, type AlterErrorCode, AlterInvalidResponse, AlterNetworkError, AlterPaymentRequired, AlterProvenanceError, AlterRateLimited, type AlterResolveHandleInput, type AlterResolveHandleOutput, AlterTimeoutError, AlterToolError, type ApiKeyConfig, type Archetype, type AssessTraitsInput, type AssessTraitsOutput, type BeginGoldenThreadInput, type BeginGoldenThreadOutput, BelowFloorError, CLAUDE_CODE, CLAUDE_DESKTOP, CLIENT_CHANNEL, CLIENT_ID, CURSOR, type ChannelFloor, type CheckAssessmentStatusInput, type CheckAssessmentStatusOutput, type CheckGoldenThreadInput, type CheckGoldenThreadOutput, type CheckMinVersionOptions, type ClaudeDesktopConfig, type ClaudeDesktopServerConfig, type ClientBelowFloorEnvelope, type ClientId, type ClientPaths, type CompleteKnotInput, type CompleteKnotOutput, type ComputeBelongingInput, type ComputeBelongingOutput, DEFAULT_DOMAIN, DEFAULT_ENDPOINT, DEFAULT_VERIFY_AT_ALLOWLIST, type DiscoveryOptions, type DiscoveryResult, type Ed25519Keypair, type EngagementLevel, FREE_TOOL_NAMES, type FloorDocument, GENERATED_TOOL_PRICING, GENERATED_TOOL_TIERS, type GenerateClaudeDesktopOptions, type GenerateMatchNarrativeInput, type GenerateMatchNarrativeOutput, type GetAgentPortfolioInput, type GetAgentPortfolioOutput, type GetAgentTrustTierInput, type GetAgentTrustTierOutput, type GetCompetenciesInput, type GetCompetenciesOutput, type GetEarningSummaryInput, type GetEarningSummaryOutput, type GetEngagementLevelInput, type GetEngagementLevelOutput, type GetFullTraitVectorInput, type GetFullTraitVectorOutput, type GetIdentityEarningsInput, type GetIdentityEarningsOutput, type GetIdentityTrustScoreInput, type GetIdentityTrustScoreOutput, type GetMatchRecommendationsInput, type GetMatchRecommendationsOutput, type GetNetworkStatsInput, type GetNetworkStatsOutput, type GetPrivacyBudgetInput, type GetPrivacyBudgetOutput, type GetProfileInput, type GetProfileOutput, type GetSideQuestGraphInput, type GetSideQuestGraphOutput, type GetTraitSnapshotInput, type GetTraitSnapshotOutput, type GoldenThreadStatusInput, type GoldenThreadStatusOutput, type GreetingRegister, HOMEPAGE_LIMITS, type HelloAgentInput, type HelloAgentOutput, type HomepageCallerVertical, type HomepageField, type HomepageFieldProvenance, type HomepageInput, type HomepageManifest, type HomepageOutput, type InitiateAssessmentInput, type InitiateAssessmentOutput, type InvocationClaims, type JsonWebKey, type JwksDocument, KNOWN_FLOOR_PUBLIC_KEYS, type ListArchetypesInput, type ListArchetypesOutput, type MCPCallOptions, type MCPCallToolResult, MCPClient, type MCPClientInfo, type MCPClientOptions, type MCPContentBlock, type MCPListToolsResult, type MCPMeta, type MCPResponse, type MCPSigningOptions, type MCPToolDefinition, MCP_PROTOCOL_VERSION, MIN_VERSION_ENDPOINT, type MatchTier, type McpServerConfig, OSC8_ALLOWED_SCHEMES, type Osc8AllowedScheme, PREMIUM_TOOL_NAMES, type PaletteFloorV1, type PaletteText, type PanelDensity, type PaymentEnvelope, type PreflightResult, type ProbeResult, type ProvenanceEnvelope, type ProvenancePayload, type ProvenanceToken, type ProvenanceVerification, type QueryGraphSimilarityInput, type QueryGraphSimilarityOutput, type QueryMatchesInput, type QueryMatchesOutput, REVENUE_SPLIT, type RecommendToolInput, type RecommendToolOutput, SDK_NAME, SDK_VERSION, type SearchIdentitiesInput, type SearchIdentitiesOutput, type SignInvocationOptions, type SignedToolDefinition, type StatusLineDensity, type StatusLineSlot, THEME_LIMITS, TIER_PRICES, TOOL_BLAST_RADIUS, TOOL_COSTS, TOOL_TIERS, type ThemeAssets, type ThemeLockEntry, type ThemeManifestV1, type ThemeMeta, type ThemeOpener, type ThemePalette, type ThemeRenderHints, type ThemeShareInput, type ThemeShareOutput, type ThemeSigil, type ThemeSignatureManifest, type ThemeStatusLine, type ThemesLockV1, type ThreadCensusInput, type ThreadCensusOutput, type ToolInputs, type ToolName, type ToolOutputs, type ToolSignatureMap, type UnwireReport, VSCODE, type VerifyIdentityInput, type VerifyIdentityOutput, type VerifyProvenanceOptions, type WireOptions, type WireReport, type WireState, type WireTarget, type WireTargetCli, type WireTargetFile, X402Client, type X402ClientOptions, type X402Settlement, type X402Signer, base64urlDecode, base64urlEncode, canonicalArgsSha256, canonicalJson, canonicalStringify, checkMinVersion, clearDiscoveryCache, compareSemver, computeKeyId, decodeDid, detectSyncedVolume, discover, encodeDid, fetchPublicKeys, generateClaudeConfig, generateClaudeDesktopConfig, generateCursorConfig, generateGenericMcpConfig, generateKeypair, keypairFromPrivateKey, loadPrivateKey, parsePaymentHeader, probeAll, probeByDir, probeClaudeCode, readWireState, resolveVerifyAt, sha256, sign, signInvocation, unwire, verify, verifyFloorSignature, verifyProvenance, verifyToolSignatures, wire, writeWireState };