Your A2A tokens stay in the store you register. The PWA stores them in localStorage by default. Server or enterprise deploys can swap that for a backend they control — file, Keychain, Vault, KMS, HSM — as long as it passes the conformance suite.
The interface
One typed contract. Hash-only storage. All methods async so backends can hit disk, IPC, or the network.
interface A2ATokenStore {
readonly kind: string;
list(workspaceId): Promise<A2AClientToken[]>;
issue(workspaceId, input): Promise<{ client, rawToken }>;
revoke(workspaceId, id): Promise<void>;
verify(workspaceId, rawToken, now?): Promise<A2AClientToken | null>;
}Register your backend at boot
import { configureA2ATokenStore } from "@aarmos/core/a2a/token-store";
import { createEncryptedFileStore } from "@aarmos/core/a2a/adapters/encrypted-file";
configureA2ATokenStore(await createEncryptedFileStore({
dir: "/var/lib/aarmos/a2a",
passphrase: process.env.AARMOS_A2A_PASSPHRASE!,
}));Everything downstream — the settings UI, the A2A adapter, verifyA2AToken — routes through the store you registered. There is no fallback path that writes to disk behind your back.
Writing your own adapter
Most adapters only need to persist and load a list of records. Use makeRecordStore and you inherit the issue / revoke / verify / expiry / hashing logic for free:
import { makeRecordStore } from "@aarmos/core/a2a/token-store";
export const myStore = makeRecordStore({
kind: "my-backend",
load: (ws) => myBackend.get(ws), // returns A2AClientToken[]
save: (ws, clients) => myBackend.put(ws, clients),
});Conformance suite (mandatory)
Every adapter — ours or yours — must pass the same suite. It pins the invariants that make BYOS safe: round-trip, verify, expiry, tenant isolation, revocation, and hash-only storage.
import {
runA2ATokenStoreConformance,
formatConformanceResults,
} from "@aarmos/core/a2a/conformance";
const results = await runA2ATokenStoreConformance(() => myStore);
console.log(formatConformanceResults(results));
if (results.some((r) => !r.ok)) process.exit(1);What we ship in-box
- localStorage — default, browser / PWA.
- encrypted-file — Node, AES-GCM + PBKDF2-SHA256 (200k iters). Same primitives as the on-device vault.
- memory — ephemeral, for tests.
Keychain, Vault, KMS, and HSM adapters ship on request as part of the Enterprise tier — or write your own against the interface above.