Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 3 additions & 3 deletions Dockerfile.local
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ ARG RUNTIME_IMAGE=debian:bookworm-20260112-slim@sha256:56ff6d36d4eb3db13a741b342
FROM ${RUST_IMAGE} AS builder
WORKDIR /build

# These named contexts are supplied by the sibling Locks Compose project. The
# Paykit contexts are crate directories, so the paykit-rs repository needs no
# Docker-owned files and its workspace target directory is never transferred.
# These named contexts are supplied by the calling build or Compose project.
# The Paykit contexts are crate directories, so the paykit-rs repository needs
# no Docker-owned files and its workspace target directory is never transferred.
RUN --mount=from=paykit-lib,target=/contexts/paykit-lib,ro \
--mount=from=paykit-sdk,target=/contexts/paykit-sdk,ro \
--mount=from=locks,target=/contexts/locks,ro \
Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,10 @@ Startup fails before bind if configuration, secrets, PostgreSQL, migrations, aut

### Local Locks demo image

`Dockerfile.local` packages this repository for sibling Locks Compose stack. It consumes checked-out Paykit Rust and Locks trees through named BuildKit contexts, then produces unprivileged local image containing server and helper binaries.
`Dockerfile.local` packages this repository for the Locks Compose stack. It
accepts pinned public Git sources or deliberate local-worktree overrides through
named BuildKit contexts, then produces an unprivileged local image containing
the server and helper binaries.

Build command, image contract, source-rewrite behavior, and generated config contract live in [`docs/local-locks-demo.md`](docs/local-locks-demo.md).

Expand Down
33 changes: 27 additions & 6 deletions docs/local-locks-demo.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,29 @@
# Local Locks demo image

`Dockerfile.local` packages Paykit Server for sibling Locks Compose stack. It is local/demo packaging, not production image.
`Dockerfile.local` packages Paykit Server for the Locks Compose stack. It is local/demo packaging, not a production image.

## Build
## Build from public pinned sources

Build from this repository with checked-out Paykit Rust and Locks source trees supplied as named BuildKit contexts:
From a fresh anonymous clone of this repository, build with the exact Paykit
Rust and Locks revisions pinned in `Cargo.toml`:

```bash
docker buildx build --load \
--build-context paykit-lib='https://github.com/pubky/paykit-rs.git#52a852995bfc457b78d32f5a45f6741766a89bba:paykit-lib' \
--build-context paykit-sdk='https://github.com/pubky/paykit-rs.git#52a852995bfc457b78d32f5a45f6741766a89bba:paykit-sdk' \
--build-context locks='https://github.com/pubky/locks.git#df5ea1b6d8dcdec3a9b5a915c3f57bca69d75c8a' \
-f Dockerfile.local \
-t paykit-server:local .
```

These contexts are anonymously reachable and reproducible. Update the URLs
together with the corresponding `Cargo.toml` pins; exact dependency-pin matches
make source drift fail closed.

## Build from local worktrees

For coordinated development, override the named contexts with local source
trees. This mode intentionally includes uncommitted source edits:

```bash
docker buildx build --load \
Expand All @@ -15,7 +34,9 @@ docker buildx build --load \
-t paykit-server:local .
```

Build uses exact local source-tree contents, including uncommitted source edits. Crate-level `paykit-lib` and `paykit-sdk` contexts avoid transferring Paykit Rust workspace target directory and require no Docker files in that repository. Locks context must exist and applies its existing source-tree exclusions.
Crate-level `paykit-lib` and `paykit-sdk` contexts avoid transferring the Paykit
Rust workspace target directory and require no Docker-owned files in that
repository. The Locks context applies its existing source-tree exclusions.

Builder runs [`scripts/prepare-local-docker-sources.sh`](../scripts/prepare-local-docker-sources.sh) against copied manifests to resolve `paykit-lib`, `paykit-sdk`, and `locks-core` from named contexts. Committed Git dependency declarations and lockfile remain unchanged. No SSH agent or Cargo credentials are mounted. Exact dependency-pin matches make source drift fail closed.

Expand All @@ -29,11 +50,11 @@ Final pinned Debian image:
- adds CA certificates and three application binaries to pinned runtime base;
- contains no source tree, Cargo cache, runnable config, DB credentials, or application secrets.

Supply `PAYKIT_CONFIG`, `PAYKIT_DATABASE_URL`, and `PAYKIT_MASTER_KEY` at runtime. Mount generated ignored local config. Sibling Compose definition owns mounts, env values, infrastructure image pins, and helper command overrides.
Supply `PAYKIT_CONFIG`, `PAYKIT_DATABASE_URL`, and `PAYKIT_MASTER_KEY` at runtime. Mount generated ignored local config. The calling Compose definition owns mounts, environment values, infrastructure image pins, and helper command overrides.

## Generated local config contract

Sibling Locks orchestration generates `.local/paykit-server/config.toml` only after local Lock Server identity exists. Directory is Git-ignored. It must replace deliberately invalid `<ACTUAL_CANONICAL_LOCK_SERVER_PUBKY>` token below with exact canonical `pubky...` value exposed by Lock Server as `credentials.lock_server_public_key`. This block is not runnable config.
Locks orchestration generates `.local/paykit-server/config.toml` only after the local Lock Server identity exists. The directory is Git-ignored. It must replace the deliberately invalid `<ACTUAL_CANONICAL_LOCK_SERVER_PUBKY>` token below with the exact canonical `pubky...` value exposed by Lock Server as `credentials.lock_server_public_key`. This block is not runnable config.

```toml
[http]
Expand Down
8 changes: 4 additions & 4 deletions docs/plans/0001-receiver-only-prototype-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ Only **EXPLICIT**, **AUTHORITATIVE SOURCE**, and **CONSTRAINT** entries may driv

The user designated these as authoritative for Locks Server ↔ Paykit Server HTTP behavior:

- `../../Pubky/locks/docs/ADRs/0020-locks-paykit-v1-integration-boundary.md`
- matching behavior in `../../Pubky/locks/locks-server/src/paykit_http_client.rs`
- [Locks ADR 0020](https://github.com/pubky/locks/blob/df5ea1b6d8dcdec3a9b5a915c3f57bca69d75c8a/docs/ADRs/0020-locks-paykit-v1-integration-boundary.md)
- matching [Locks Paykit HTTP client](https://github.com/pubky/locks/blob/df5ea1b6d8dcdec3a9b5a915c3f57bca69d75c8a/locks-server/src/paykit_http_client.rs)

### Product flow

Expand All @@ -40,8 +40,8 @@ Current `../paykit-rs` code/specifications define dependency behavior. They are
**EXPLICIT**:

- Canonical Locks creator, reader, bundle, addressed lock-resource identifiers,
and Paykit-payment policy validation use `locks-core` pinned at revision
`06bc63c4b5ff7df194f26f3f3fecb8dab4d28995`; Paykit Server does not duplicate
and Paykit-payment policy validation use `locks-core` pinned at public revision
`df5ea1b6d8dcdec3a9b5a915c3f57bca69d75c8a`; Paykit Server does not duplicate
their parsing, canonicalization, or policy grammar.

## Actors and key boundaries
Expand Down
6 changes: 3 additions & 3 deletions docs/plans/0002-receiver-only-prototype-implementation.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@

**Architecture:** A virtual Rust workspace contains one server crate and one black-box E2E crate. `paykit-server` owns HTTP, application workflows, encrypted PostgreSQL persistence, and worker orchestration; it calls `paykit-sdk` rather than recreating Paykit protocols. Creator authority, one BIP84 account xpub/account index, address allocation, receiver Noise key, and SDK state are isolated per Creator inside one supported server process. `paykit-server-e2e` starts the real Axum application against PostgreSQL and verifies committed cross-boundary and cross-Creator isolation contracts.

**Tech Stack:** Rust edition 2024 (MSRV 1.91.1), Tokio, Axum, SQLx/PostgreSQL, `paykit-sdk`/`paykit-lib` pinned to inspected `paykit-rs` commit `81fd0e5124aac1fd782811fd968109a5972cd323`, XChaCha20-Poly1305, HKDF-SHA256, Ed25519, Electrum client.
**Tech Stack:** Rust edition 2024 (MSRV 1.91.1), Tokio, Axum, SQLx/PostgreSQL, `paykit-sdk`/`paykit-lib` pinned to inspected `paykit-rs` commit `52a852995bfc457b78d32f5a45f6741766a89bba`, XChaCha20-Poly1305, HKDF-SHA256, Ed25519, Electrum client.

**Authoritative requirements:**
- `docs/plans/0001-receiver-only-prototype-design.md`
- `../../Pubky/locks/docs/ADRs/0020-locks-paykit-v1-integration-boundary.md`
- Matching Locks behavior in `../../Pubky/locks/locks-server/src/paykit_http_client.rs`
- [Locks ADR 0020](https://github.com/pubky/locks/blob/df5ea1b6d8dcdec3a9b5a915c3f57bca69d75c8a/docs/ADRs/0020-locks-paykit-v1-integration-boundary.md)
- Matching [Locks Paykit HTTP client](https://github.com/pubky/locks/blob/df5ea1b6d8dcdec3a9b5a915c3f57bca69d75c8a/locks-server/src/paykit_http_client.rs)

**Hard boundary:** Do not implement unsupported Paykit wire/Encrypted-Link behavior locally. Delegate it to the pinned `paykit-sdk` dependency.

Expand Down
22 changes: 16 additions & 6 deletions docs/plans/0004-local-locks-compose-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@

**Tech stack:** Rust 1.91.1, Axum, `paykit-sdk`, PostgreSQL/SQLx, Docker multi-stage builds, Pubky static testnet, Bitcoin Core regtest, BDK Electrum.

**Publication note:** The original peer implementation plan was intentionally
not included in the fresh public Locks history. The public cross-service
contract is [Locks ADR 0020](https://github.com/pubky/locks/blob/df5ea1b6d8dcdec3a9b5a915c3f57bca69d75c8a/docs/ADRs/0020-locks-paykit-v1-integration-boundary.md).
Public image builds use anonymous pinned Git contexts; sibling worktrees remain
an explicit local-development override.

---

## Requirement provenance
Expand All @@ -26,12 +32,12 @@

### AUTHORITATIVE SOURCE

- `../paykit-rs/specs/pubky-auth-companion-claims.md`.
- `../paykit-rs/paykit-sdk/src/pubky_session/companion_claim.rs`.
- [Paykit companion-claim specification](https://github.com/pubky/paykit-rs/blob/52a852995bfc457b78d32f5a45f6741766a89bba/specs/pubky-auth-companion-claims.md).
- [Paykit SDK companion-claim implementation](https://github.com/pubky/paykit-rs/blob/52a852995bfc457b78d32f5a45f6741766a89bba/paykit-sdk/src/pubky_session/companion_claim.rs).
- `paykit-server/src/bitkit_claim.rs` for exact `watch-only-account-v1` payload and receiver validation.
- `paykit-server/src/real_setup.rs` for setup commit ordering and xpub validation.
- `README.md` and `config/paykit-server.example.toml` for supported runtime/config behavior.
- Peer plan: `../../Pubky/locks/docs/plans/0042-local-paykit-integration-demo.md`.
- Public peer contract: [Locks ADR 0020](https://github.com/pubky/locks/blob/df5ea1b6d8dcdec3a9b5a915c3f57bca69d75c8a/docs/ADRs/0020-locks-paykit-v1-integration-boundary.md).

### CONSTRAINTS OBSERVED IN CURRENT CODE

Expand Down Expand Up @@ -126,7 +132,7 @@ No implementation task may invent an answer to these gates.

**Files:**
- Create/Modify: `docs/plans/0004-local-locks-compose-integration.md`
- Review: `../../Pubky/locks/docs/plans/0042-local-paykit-integration-demo.md`
- Review: public [Locks ADR 0020](https://github.com/pubky/locks/blob/df5ea1b6d8dcdec3a9b5a915c3f57bca69d75c8a/docs/ADRs/0020-locks-paykit-v1-integration-boundary.md)

**Steps:**
1. Resolve all gates one question at a time.
Expand Down Expand Up @@ -265,8 +271,12 @@ No implementation task may invent an answer to these gates.
cargo test --workspace
cargo clippy --workspace --all-targets -- -D warnings
cargo fmt --check
docker buildx build --build-context paykit-lib=../paykit-rs/paykit-lib --build-context paykit-sdk=../paykit-rs/paykit-sdk --build-context locks=../../Pubky/locks -f Dockerfile.local -t paykit-server:local .
docker buildx build --load \
--build-context paykit-lib='https://github.com/pubky/paykit-rs.git#52a852995bfc457b78d32f5a45f6741766a89bba:paykit-lib' \
--build-context paykit-sdk='https://github.com/pubky/paykit-rs.git#52a852995bfc457b78d32f5a45f6741766a89bba:paykit-sdk' \
--build-context locks='https://github.com/pubky/locks.git#df5ea1b6d8dcdec3a9b5a915c3f57bca69d75c8a' \
-f Dockerfile.local -t paykit-server:local .
git diff --check
```

The sibling Locks plan must add executable wrapper commands that load ignored generated credentials and run explicit `TEST_DATABASE_URL` suites plus the Compose smoke without printing secrets.
The corresponding Locks integration must add executable wrapper commands that load ignored generated credentials and run explicit `TEST_DATABASE_URL` suites plus the Compose smoke without printing secrets.