diff --git a/docs/conformance.md b/docs/conformance.md index 7a0ed352..1e50b8da 100644 --- a/docs/conformance.md +++ b/docs/conformance.md @@ -395,6 +395,21 @@ temporary directory empty and the listing unchanged. And a body over the configured cap is 413 `BlobTooLarge`, a body that would break the account quota is 403 `AccountQuotaExceeded`, and neither leaves a file behind. +### Signing in, driven by somebody else's client + +Two OAuth client libraries sign in to this server in the test suite, and +neither is this project's code. Each one resolves the account's DID, finds +this server's metadata, pushes its request with DPoP, exchanges the code, +checks `iss` and `sub`, writes a record, and refreshes. + +| Client | Test | What signs in | +| --- | --- | --- | +| Bluesky's `@atproto/oauth-client-node`, at the version `tools/oauth-interop/package.json` pins | `crates/didbot-serve/tests/oauth_interop.rs`, against a running `didbot-pds` | a public native client with a loopback redirect, and a confidential web client using `private_key_jwt` whose metadata and key set this server fetches from the client's own origin | +| jacquard-oauth, at the version `Cargo.lock` pins | `crates/didbot-serve/tests/oauth_standard_client.rs`, against the router in process | a public loopback client, a public web client by handle, and a confidential client with jacquard's keyset | + +The Node library departs from the profile in three places, which the top of +`oauth_interop.rs` lists. The profile is what this server is held to. + ## Account state, and where it does not map onto the wire `HostedAccount` carries an `AccountState` — whether its data exists — and a diff --git a/docs/testing.md b/docs/testing.md index 55618a52..c477d388 100644 --- a/docs/testing.md +++ b/docs/testing.md @@ -55,7 +55,8 @@ command column is what runs it. | Check | Command | What covers it | | --- | --- | --- | | A full sign-in from a foreign client: push, decision, approval, code, bound token, write, refresh, replay | `cargo test -p didbot-serve --test oauth_account_flow` | the whole flow against the real router, with this project's own client | -| The loopback client form, and a client whose metadata is served from a hostile origin | none | none | +| Bluesky's own `@atproto/oauth-client-node` signs in to a running server as a public native client and as a confidential web client, and writes before and after a refresh | `npm ci --prefix tools/oauth-interop`, then `cargo test -p didbot-serve --test oauth_interop` | `crates/didbot-serve/tests/oauth_interop.rs` runs `tools/oauth-interop/sign-in.mjs` against `didbot-pds` and approves each sign-in as `didbot-agentd` does; without `node` or the installed tree it passes having said so | +| The loopback client form, and a client whose metadata is served from a hostile origin | `cargo test -p didbot-serve --test oauth_standard_client` and `--test oauth_interop` | jacquard-oauth's loopback client and `@atproto/oauth-client-node`'s sign in; a hostile origin is not driven | | Scope narrowing: a token cannot write outside its grant, a tightened ceiling narrows the next write | `cargo test -p didbot-serve --test token_scope` | `crates/didbot-serve/tests/token_scope.rs` and `crates/didbot-scope/tests/ceiling_boundary.rs` | | A scripted agent that approves everything, against the default ceiling | none | none | | A second agent cannot redeem a consent reference it did not receive | `cargo test -p didbot-serve --test oauth_account_flow` | the account check is the credential's, and the flow test drives it from both sides | diff --git a/tools/README.md b/tools/README.md index 987fb5bf..f39e2e15 100644 --- a/tools/README.md +++ b/tools/README.md @@ -6,6 +6,10 @@ manifest, so nothing here is built by `cargo build --workspace`, tested by cargo clippy --manifest-path tools/Cargo.toml --all-targets -- -D warnings +`oauth-interop/` is a Node program rather than a member of that workspace: +`crates/didbot-serve/tests/oauth_interop.rs` runs it, and `docs/testing.md` +says how. + ## xray — the reference index `git grep` is a text search over a language with modules, `use` re-exports,