Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
e0d3ebb
API
lirbank Jul 17, 2026
15fb5bc
API
lirbank Jul 17, 2026
e2b02a5
Spec
lirbank Jul 17, 2026
54fb2a5
Deps
lirbank Jul 17, 2026
a09252c
Contract
lirbank Jul 17, 2026
b7093dc
Renam
lirbank Jul 17, 2026
b0688e2
Update AGENTS.md
lirbank Jul 17, 2026
5395a0c
Update AGENTS.md
lirbank Jul 17, 2026
b333067
Spec
lirbank Jul 17, 2026
1d32a60
Update contracts.ts
lirbank Jul 17, 2026
eac78cc
Error handling
lirbank Jul 17, 2026
b1e765e
Spec
lirbank Jul 17, 2026
28916b7
Update contracts.ts
lirbank Jul 17, 2026
62f9f8c
Update AGENTS.md
lirbank Jul 17, 2026
c3e1a44
Spec
lirbank Jul 17, 2026
ad15957
Spec
lirbank Jul 18, 2026
e8b15b2
Spec
lirbank Jul 18, 2026
d28ef7c
Spec
lirbank Jul 18, 2026
b4ab586
Update contracts.ts
lirbank Jul 19, 2026
ae4d07b
Update contracts.ts
lirbank Jul 19, 2026
ea1c3ae
Deps
lirbank Jul 19, 2026
b61d116
Spec
lirbank Jul 19, 2026
746678a
Update AGENTS.md
lirbank Jul 19, 2026
ea480c6
Update mechanisms.ts
lirbank Jul 19, 2026
edc4f52
Update AGENTS.md
lirbank Jul 19, 2026
6e81cc3
Spec
lirbank Jul 20, 2026
623f92a
Tests
lirbank Jul 20, 2026
c6dbe87
Tests
lirbank Jul 20, 2026
7b67583
Update package.json
lirbank Jul 20, 2026
284b243
Tests
lirbank Jul 20, 2026
8dafabc
Create SKILL.md
lirbank Jul 20, 2026
9c1be98
Tests
lirbank Jul 20, 2026
0cb6f4e
Update make-session-hmac-codec.test.ts
lirbank Jul 21, 2026
6cc75ae
Tests
lirbank Jul 21, 2026
e9f1e02
Update make-session-hmac-codec.test.ts
lirbank Jul 21, 2026
3f7b414
Update make-session-hmac-codec.test.ts
lirbank Jul 21, 2026
a278eba
Update make-session-hmac-codec.test.ts
lirbank Jul 21, 2026
9deed35
Update SKILL.md
lirbank Jul 21, 2026
475c0ff
Create skills
lirbank Jul 21, 2026
426064d
Deps
lirbank Jul 21, 2026
fbf3431
Update make-session-hmac-codec.test.ts
lirbank Jul 21, 2026
d975ad4
Update make-session-hmac-codec.test.ts
lirbank Jul 21, 2026
55e9bbe
Update make-session-hmac-codec.test.ts
lirbank Jul 21, 2026
50ce918
Update make-session-hmac-codec.test.ts
lirbank Jul 21, 2026
7b440d2
Tests
lirbank Jul 21, 2026
4dbd72a
Update crypto.test.ts
lirbank Jul 21, 2026
b0812c3
Skills
lirbank Jul 22, 2026
9868c9d
Remove hard line breaks
lirbank Jul 22, 2026
cbc91fb
Session lifecycle spike
lirbank Jul 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions .agents/skills/test-one/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
---
name: test-one
description: Write exactly one approved behavioral test for one contract unit, run it, and stop before implementation. Use after test planning when the user has selected a claim.
---

# Test one

Turn one approved behavioral claim into one reviewable test.

## Scope

1. Require one target contract unit and one claim explicitly supplied or approved by the user. If either is absent or ambiguous, ask before working. If the user supplies multiple claims, state that `/test-one` accepts one claim and stop without presenting a questionnaire.
2. Stay within that claim. Do not add adjacent cases, refactor unrelated tests, or change production code.
3. If no authority determines the expected behavior, stop and ask rather than inventing it.
4. Follow the approved plan's responsibility boundary and resolved prerequisites; do not reopen or expand them.

## Before writing

State briefly:

- The selected behavioral claim.
- The test oracle.
- Where the test will live.
- Why existing tests do not already prove it.

Derive the test oracle from an authority, never from the implementation under test.

The user's claim approval is the authorization to proceed; do not add another approval gate unless expected behavior is unclear.

## Write the test

- Follow the test-organization and style rules in `AGENTS.md`.
- Add exactly one `test` or `test.each` declaration.
- Use `test.each` only when every named case is equivalent evidence for the same claim.
- Match the target file's established behavioral grouping.
- Keep setup local and deterministic.
- Assert the exact public outcome.
- Use scenario comments when a non-obvious transition or sequence matters to the claim; state intent, never mechanics already clear from the code.

Do not edit contracts, production code, unrelated tests, or work-queue files.

## Verify

Run the narrowest command that executes the new test.

- Fix test syntax, typing, or setup errors until the test reaches the selected behavior.
- If it fails for the expected behavioral reason, report it as red.
- If it passes immediately, report it as green on arrival; do not weaken the test or change production code to force red.
- If another failure prevents the selected behavior from being reached, report the blocker without expanding scope.

## Output

Report:

```text
Claim: <selected claim>
Oracle: <expected result or decision rule>
Test: <file and test name>
Result: <red, green on arrival, or blocked> — <reason>
Command: <narrow command>
```

Stop after reporting so the user can review the test before implementation.
76 changes: 76 additions & 0 deletions .agents/skills/test-plan/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
---
name: test-plan
description: Plan test coverage for one contract unit at a time. Use when identifying covered, partial, missing, unclear, or out-of-scope behavioral claims before writing tests.
---

# Test plan

Produce a compact assurance inventory for one contract unit. A contract unit is a public factory, adapter, namespace method, parser, or similarly coherent behavioral boundary; it is not necessarily one physical file.

## Scope

1. Require the user to name one target contract unit. If the target is absent or ambiguous, ask before investigating.
2. Stay within that target. Do not rank gaps across the repository or propose work in unrelated modules.
3. Record cross-unit discoveries under `Parked follow-ups` without pursuing them.

## Responsibility boundary

Before inventorying claims:

1. Identify the behavior the target owns and its settled, separately testable collaborators from user requirements and the authoritative documentation and type structure identified by `AGENTS.md`. Implementation may reveal candidate boundaries, but never behavior or a test oracle; ask when ownership is unclear.
2. Inspect direct collaborator tests for delegated behavior required by the target. If required behavior lacks direct evidence, report `/test-plan <collaborator>` as a prerequisite and stop before the target inventory.
3. Inventory only target-owned policy, translation, validation, and observable wiring. Do not count collaborator conformance as target coverage or require internal call-count evidence.

## Claims and evidence

Gather behavioral claims from the authorities relevant to the target:

1. Requirements supplied by the user.
2. The authoritative contract and mechanism documentation identified by `AGENTS.md`.
3. Relevant threat-model decisions and governing standards.

Use the work queue to find known gaps and target tests to classify evidence. Collaborator tests establish prerequisites and prevent duplication; they never prove a target-owned claim. Existing tests and implementation do not determine expected behavior.

## Inventory

Build the complete behavioral claim inventory for the target. Group claims by the unit's real behavioral concerns or failure modes so the groups can orient the test file. Reuse sibling group names where they fit; never impose a fixed taxonomy. Include positive behavior, denial or failure behavior, boundaries, side effects, time, and concurrency only where the authorities require them.

Give every claim exactly one status:

- `Covered` — existing evidence directly proves the claim.
- `Partial` — evidence proves only part of the claim.
- `Missing` — the claim has no direct evidence.
- `Unclear` — no authority determines the expected behavior.
- `Out of scope` — an authority explicitly places responsibility elsewhere.

Number every claim sequentially in the report. The numbers are local references for selecting a claim from that report, not permanent identifiers.

For covered or partial claims, cite the relevant test by name and file. For missing or partial claims, briefly state the defect the evidence should catch. Do not invent requirements or add speculative edge cases.

## Output

Report an unresolved prerequisite after the responsibility boundary as `Prerequisite: /test-plan <collaborator> — <reason>`, then stop. Otherwise use this structure:

```text
Target: <contract unit>

Responsibility boundary
- Owns: <target responsibilities>
- Delegates: <collaborator → delegated responsibilities, or None>

<Behavior group>
- [<number>] <Status>: <claim>. <Evidence or brief gap reason>

Questions
- <Only genuinely unresolved requirements; omit when empty>

Recommended next test
- [<number>] <One missing or partial claim and its test oracle, with a short reason; or `None` when every claim is covered or otherwise resolved>

Parked follow-ups
- <Cross-unit discovery; omit when empty>
```

Keep each entry concise, but do not cap or sample the inventory. Completeness is local to the target.

Do not edit files, write test code, or propose implementation. Stop after the inventory so the user can approve the recommended test target or choose another.
1 change: 1 addition & 0 deletions .claude/skills
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"chat.disableAIFeatures": true,
// "chat.disableAIFeatures": true,
"editor.accessibilitySupport": "off",
"editor.codeActionsOnSave": { "source.fixAll.eslint": "explicit" },
"editor.defaultFormatter": "esbenp.prettier-vscode",
Expand Down
82 changes: 56 additions & 26 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,36 +1,40 @@
# Agent guidelines

- Use `bun run check` after edits to type check all workspaces
## Commands

## Development workflow
- Use `bun run check` after edits to type check all workspaces

- Use `packages/auth/README.md` as the source of intent — it documents the target API and wins over code
- Order of work: types (signatures) → tests → implementation. Signatures make the contract concrete, tests encode it, implementation satisfies it.
- When designing an adapter interface, ask what the lazy implementation does — it must fail closed (deny access), never open
- Type files are split by layer (see SPEC.md "Adapter layering"): contracts, mechanisms, bindings, configs — file organization mirrors the layers
- Generate code + tests together in small chunks
- Human reviews for: unnecessary complexity, over-engineering, maintainability
- Iterate until tight
- Tests become the true spec — the README is the contract they encode
## Session start

## Documentation map
Read before working, in order:

Roles (decided 2026-07-16): README = contract, SPEC = rationale, TODO = queue.
1. `packages/auth/src/spike/contracts.ts` + `spike/mechanisms.ts`
2. `TODO.md`
3. `SPEC.md`

Now:
## Documentation map

- `packages/auth/README.md` — the contract: target API, drives implementation. Where it disagrees with the code, the README wins.
- `packages/auth/src/spike/contracts.ts` + `spike/mechanisms.ts` — the contract: the typed API spec. Wins over README and code.
- `SPEC.md` — rationale and dated decision record. Partially stale; never treat it as the contract.
- `TODO.md` — work queue from the 2026-07 repo review. Deliberately uncommitted.
- `TODO.md` — the work queue. Gitignored, local to this machine. Never delete items: mark `[x]` with a resolution note; add new items for follow-on work.
- `packages/auth/README.md` — stale. At promotion it is rewritten from the settled spike and becomes the contract.

Destination (hold until the contract is finished and proven by the builder factory implementation):
At promotion (only after the implementation has proven the contract):

- `/README.md` (root, new) — rationale: philosophy, positioning, security model, dated decisions, absorbed from `SPEC.md`
- `packages/auth/README.md` — contract plus behavioral docs (TTL/session mechanics move here or to a linked docs file)
- `SPEC.md` — deleted once fully dissolved
- Queue moves to issues, or `TODO.md` remains

Don't start the doc reorganization ahead of that milestone — SPEC content can't be sorted into rationale vs behavioral docs until the contract settles.
## Development workflow

- Order of work: types → tests → implementation, in small chunks — one unit at a time
- Design adapter interfaces so the laziest implementation is safe: a no-op adapter may only deny access (fail closed), never grant it. If a lazy adapter could grant access, move that obligation into core or a shipped mechanism.
- Type files are split by layer; file organization mirrors the layers:
- Contracts — the adapter interfaces, the product. Semantic, never mechanical; core runs on anything satisfying them.
- Mechanisms — logic shipped as adapters, environment-free. No framework imports, ever.
- Bindings — environment glue. Zero logic — an if-statement means the logic moves down into a mechanism.
- Configs — pre-composed config values. Data only — composition plus literals, no functions of their own.

## Quality over speed

Expand All @@ -40,8 +44,7 @@ This is security-critical code.
- Don't add edge cases that weren't asked for
- Don't over-abstract — abstractions must earn their keep
- Don't add "just in case" code
- Match the style and conventions already in the codebase
- Every test should be necessary — don't test unlikely edge cases
- Every test should be necessary
- Code should be simple enough to explain in a security audit

## Code style
Expand All @@ -51,28 +54,55 @@ This is security-critical code.
- ESM only, no CommonJS
- TypeScript only, no transpile to JS
- Factories should be prefixed with `make` (e.g., `makeAuth`, `makeMemoryAdapters`)
- No optional parameters and no defaults — anywhere, API or config
- Never export local symbols
- Use TS/JS style comments
- Doc blocks are `/** */`, prose only — never `@param`/`@returns` tags, types carry the signatures
- In contract/spec files doc blocks are spec text — held to completeness, state every constraint the type can't show
- Everywhere else comments are held to necessity — only what code can't express, never narration
- Comment tone: professional library API docs — never design rationale, internal notes, or decision history; those belong in SPEC.md

## Error handling

- All public API functions return `Result<T>` — never throw
How methods return (commands, queries, adapters, throws) is specified by the `Result` doc block in the contracts.

- Use `result.ok()` for success, `result.fail()` for expected failures
- Invariants: Never use type assertions (`as`). Throw instead — surfaces bugs immediately. Comment each invariant `Invariant: reasoning`
- Must prove the error with a test before adding try-catch

## TDD (critical)
## Tests

### Vocabulary

- Authority — the source that determines expected behavior, following the documentation map; e.g. a contract, requirement, governing standard, or user/domain expert
Example: The contract says a token is expired only when `expiresAt < now`
- Behavioral claim — what must be true
Example: A token is not expired when `expiresAt === now`
- Test oracle — the expected result or decision rule for a given case
Example: `expired` is `false`, encoded as `expect(decoded?.token.expired).toBe(false)`

### TDD (critical)

Every test proves one behavioral claim using a test oracle derived from an authority. The implementation under test is never an authority or test oracle. When no authority determines the expected behavior, ask the user.

Place each claim at the lowest contract unit that owns the behavior, and establish required collaborator coverage before wrapper tests. Wrapper tests cover the wrapper's policy, translation, validation, and observable wiring; collaborator conformance belongs in the collaborator's test file. Prove wiring through public outcomes, not internal call counts.

### Organization

- NEVER write tests based on implemented code
- ALWAYS write tests based on expected behavior (spec, requirements, user input)
- When unsure about expected behavior, ask the user
- One contract unit per test file; the filename identifies it, so don't repeat it in an outer `describe`
- Group `describe` blocks by the unit's real behavioral concerns or failure modes; reuse sibling group names where they fit, never impose a fixed taxonomy
- Prefer no more than one `describe` level; use an ungrouped `test` when grouping adds no orientation
- Use `test` and `test.each`, not `it`
- Test names state complete behavioral claims using API vocabulary; name the responsible public operation or subject when the group does not
- Use scenario comments when a non-obvious transition or sequence matters to the claim; state intent, never mechanics already clear from the code
- Split multiple public units into separate test files when practical

## Prose style

- Use sentence case, never title case
- Don't use the word "code" with regards to OTP (use "otp")
- OTP: uppercase in prose, `Otp*`/`otp` in identifiers; never call it a "code"

## Code review instructions

- Look for dead code
- Look for useless assertions in tests
- Look for unnecessary complexity and over-engineering
Loading