Skip to main content
[AVAILABLE], output below is a real run, this session, commit 651497a.

Goal

Confirm, by causing each failure yourself, that a session credential is genuinely single-use and time-bounded, not just documented as such.

Prerequisites

  • Read Credential isolation, this guide exercises InMemorySessionCredentialVault directly, the mechanism that page describes.

Steps

This exact scenario already exists as examples/tutorials/58-session-credentials/, reuse it rather than writing a parallel harness. It constructs a vault directly, no gateway, no server, and puts a real credential through four cases: happy path, expiry, reuse, and revocation.
// examples/tutorials/58-session-credentials/run.ts (excerpt)
const credentials = new InMemoryCredentialVault();
credentials.setCredential("oracle", { value: Object.freeze({ token: "oracle-secret-9876" }) });

const sessionCredentials = new InMemorySessionCredentialVault({
  credentials,
  clock: new SystemClock(),
  idGenerator: new RandomIdGenerator(),
  lifetimeMs: 1_000,  // short, so expiry is observable in a few seconds
});
Run it:
node_modules/.bin/tsx examples/tutorials/58-session-credentials/run.ts

Verify

Real output, this session:
Happy Path
--------------------------------------------------
Issued  : ae31c202-8e9d-4411-9aac-b3ece1f2151a
Consumed: token
✓ Consumed within the lifetime window.

Expiry
--------------------------------------------------
Waiting past the 1-second lifetime...
✓ Consumption after expiry rejected:
  Session credential has expired: f3ed26b0-80bc-44e9-b3ad-b7e126679e6a.

Reuse
--------------------------------------------------
✓ First consumption succeeded.
✓ Second consumption rejected:
  Session credential has already been used: a8c9cd67-ed37-4e15-ae18-dcce964c4758.

Revocation
--------------------------------------------------
✓ Session credential revoked before use.
✓ Consumption after revocation rejected:
  Session credential has been revoked: ff2a976c-e5dd-4f9c-ba94-0f2377e62fa2.
All three negative cases (expired, already-consumed, revoked) throw distinct, readable errors naming the session credential ID, none of them silently succeed or return an empty result, each is a real thrown Error.

Next steps

  • Change lifetimeMs to something longer or shorter and rerun, confirm the expiry window actually moves with it.
  • Call consume() before issue() resolves (a nonexistent ID) and observe the error message names the ID, not a resolved credential value, matching the never-leaks guarantee in Credential isolation.

Troubleshoot

  • Expiry case doesn’t reject. lifetimeMs and the sleep() duration in the tutorial are both short (1 second, 1.1 second wait) to keep the tutorial fast, if you’ve modified either independently, they can drift out of sync.
  • You want this wired to a real connector, not called directly. See Add a connector with the Connector SDK, and examples/tutorials/59-secure-connectors/run.ts for the full path: gateway attestation, a SessionCredentialSecureConnector, and destruction of the credential immediately after use.

Next

Add a connector with the Connector SDK

Where a connector actually receives the credential this guide issued.

Gateway attestation

What has to succeed before a session credential can even be issued.