/** * AWS Signature Version 4, by hand. * * **Why by hand.** `@trazum/core` has zero runtime dependencies and a test that * fails the build if one appears. That is a security property rather than a * packaging preference: this library reads people's prompts, and every * dependency is somebody else's code reading them too. The AWS SDK is roughly * a hundred packages to sign one request. * * **WebCrypto, not `node:crypto`.** The browser-safe entry point cannot reach a * Node builtin — `apps/web` bundles this library, and a single `node:` import * anywhere in that graph fails the build. `crypto.subtle` exists in both, so * signing works in a browser and in the CLI without a second implementation. * Everything here is therefore async, which HMAC-SHA256 does not need to be and * `crypto.subtle` insists on anyway. * * **What is not asserted, and it matters.** There is no AWS-published * known-answer vector in the tests. This environment cannot reach the internet * to fetch one and cannot reach AWS to try a real call, so the tests check the * canonical strings this builds — which are derivable from the specification by * reading — plus the cryptographic properties that any correct signer has. A * systematically wrong canonicalisation that is wrong *consistently* would pass * all of them. The first real request against Bedrock is the proof, and until * somebody makes one this is careful code rather than verified code. */ /** * `20260810T140102Z` and `20260810`, from one instant. * * Both derive from the same `Date` rather than being formatted twice. The * classic SigV4 bug is a request signed at 23:59:59.9 whose date stamp comes * from the next day: the credential scope and the timestamp disagree by one * day, AWS rejects it, and it happens roughly once per thousand requests at * midnight UTC and never in a test. */ export declare function amzDates(now: Date): { amzDate: string; dateStamp: string; }; /** * The signing key: four chained HMACs, each keyed by the last. * * The chain is what scopes a signature to one day, one region and one service, * so a leaked signature is not a leaked credential. `AWS4` prefixes the secret * and is part of the specification rather than decoration. */ export declare function signingKey(secretAccessKey: string, dateStamp: string, region: string, service: string): Promise; export interface SignInput { method: string; /** Already-encoded path, e.g. `/model/anthropic.claude-v2/invoke`. */ path: string; host: string; region: string; service: string; body: string; accessKeyId: string; secretAccessKey: string; /** Present for temporary credentials, and signed when it is. */ sessionToken?: string; now: Date; } /** * The headers a signed request carries. * * Returned rather than mutated onto a request, so this is a pure function of its * input and a test can read every byte of what it produced. */ export interface SignedHeaders { authorization: string; 'x-amz-date': string; 'x-amz-content-sha256': string; 'x-amz-security-token'?: string; } /** * Builds the canonical request, exactly as the specification orders it. * * Exported for the tests, because this string is where a signer goes wrong. * Every field is joined with a newline, headers are lowercased and sorted, and * the trailing newline after the header block is required — omit it and every * signature is wrong in a way whose only symptom is `403 SignatureDoesNotMatch`. */ export declare function canonicalRequest(input: SignInput): Promise<{ canonical: string; signedHeaderNames: string; payloadHash: string; }>; /** The full `Authorization` header value, and the headers that go with it. */ export declare function signRequest(input: SignInput): Promise; //# sourceMappingURL=aws-sigv4.d.ts.map