1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
[]
= "cratefield-cli"
= "The fz CLI for Cratefield ventures: migrations collect/apply, doctor, modules, push"
= "README.md"
= ["cratefield", "cli", "migrations", "wrangler", "d1"]
= ["command-line-utilities", "development-tools"]
= ["src/**/*", "examples/**/*", "README.md"]
= "0.2.0"
= true
= true
= true
= true
[]
= true
[]
# `fz migrations apply --dialect postgres` (issue #18): pulls the
# native-only Postgres adapter and a tokio runtime to drive it. Opt-in so
# the default fz dependency graph stays free of sqlx and tokio — a
# venture's wasm build must never see them.
= ["dep:cratefield-adapter-postgres", "dep:tokio"]
# `fz push send`'s network leg (issue #184): the runtime's own HTTP client —
# reqwest behind the outbound policy — and the tokio runtime it needs. Opt-in
# for the same reason `postgres` is, and the live-proof tool is documented as
# needing it (README, issue #186).
#
# A feature-gated *send* is not the feature-gated *doctor* the push-wiring
# note below refuses. The difference is what an `fz` without the feature
# does: `fz push send` says, in one line, exactly what to rebuild, while a
# doctor compiled without a check reports a clean bill and says nothing. Loud
# absence is a build option; silent absence is not. Everything else under
# `fz push` — keygen, inspect-subscription, and `send --dry-run`, which
# reports the transport's wiring — works in every build.
#
# This is never a feature a **venture** turns on: `cratefield-runtime-native`
# `compile_error!`s on wasm32 and a generated venture depends on this crate
# beside a wasm `cdylib`, so flipping it there breaks the build of the thing
# the venture deploys. A send-capable `fz` is installed separately
# (`cargo install cratefield-cli --features push-send`) and the Docker image
# is built with it.
#
# It pulls the whole native runtime — axum, redis, croner,
# tracing-subscriber — to obtain one `ReqwestClient` and one `TokioClock`,
# and the alternative was weighed: an `http-client` feature on
# `cratefield-runtime-native` that carried the ports without the server.
# Not taken, deliberately.
#
# - That crate's module graph is not separable along that line today.
# `ports/mod.rs` itself is built on axum types (`HeaderMap`,
# `HeaderName`, the client-IP resolution the server middleware calls),
# so an `http-client` build would have to `cfg` the ports module, the
# runtime, the server, cron and the tracing setup — and every one of
# those becomes a configuration nothing in CI compiles unless a matrix
# leg is added for it.
# - The cost it buys back is build time for one native binary that is
# compiled once and installed. Nothing ships this graph: the venture's
# wasm build never sees this crate (that is what the `compile_error!`
# enforces), and the image already carries a Rust toolchain.
# - The point of the live proof is that the send goes through *the
# client the runtime uses*, wired the way `serve()` wires it. A leaner
# dependency edge that reached a differently-assembled client would
# make the proof prove less.
#
# Revisit it if a second consumer wants the same thing, which is when the
# split stops being a change made for one caller.
= ["dep:cratefield-runtime-native", "dep:tokio"]
[]
= { = true }
= { = true }
# `fz doctor` reads the push environment through the same `build_push` the
# runtimes do (issue #191), so the doctor and `serve()` cannot check different
# variable names. Pure Rust and native-safe: the push adapters speak HTTP
# through the `HttpClient` port and pull no tokio, sqlx or OpenSSL.
#
# **Not** optional, unlike `postgres` below, and the difference is deliberate.
# `fz` is built once and installed; a feature-gated doctor check is a doctor
# that silently checks less depending on how somebody's `fz` was compiled,
# which is the same class of invisible drift this crate exists to remove. The
# cost is that every `fz` links the three adapters and their crypto, and that
# `cratefield-push-wiring` must be first-published before `cratefield-cli`
# (docs/RELEASING.md).
= { = true }
# `fz push vapid keygen` (issue #184) mints the P-256 key pair with the same
# signer the adapters present their provider tokens with, so the public half
# it prints is the one `WebPush::public_key()` derives — not a second
# derivation that could disagree about the point encoding.
= { = true }
# `fz push inspect-subscription` validates with the Web Push adapter's own
# rules — `vapid::origin_of` for the audience, `ece::SubscriptionKeys` for
# the two keys — so a subscription the CLI accepts is one the adapter
# accepts. Already in the graph through `cratefield-push-wiring`; named here
# because this crate calls it directly.
= { = true }
= { = true }
= { = true }
= { = true }
# The VAPID scalar and its base64url form are key material: cleared on drop,
# the workspace convention (`crates/kms`, `crates/secrets`, the adapters).
= { = true }
# Draws the VAPID private scalar. Backend selection is the final crate's job
# in this workspace, which for a native-only binary is the default one; the
# line matches `cratefield-kms` and `cratefield-push-auth`.
= { = true }
= { = true }
= { = true }
= { = true }
= { = true }
= { = true }
= { = true }
= { = true }
= { = true, = true }
# `push-send` only: the native runtime's reqwest client and its outbound
# policy. Native-only by construction (the crate refuses to compile on wasm),
# which is why it is optional and off by default.
= { = true, = true }
# `net` and `time` on top of the workspace pin: reqwest needs the IO and
# timer drivers enabled, and `enable_all()` silently enables neither without
# them — a runtime that then panics on the first request.
= { = true, = true, = ["net", "time"] }
[]
# The push unit tests send through a scripted `HttpClient` rather than the
# network. Path-only: `cargo publish` resolves dev-dependencies against
# crates.io (the workspace manifest's note), and a path-only one is stripped
# from the packaged manifest.
= { = "../testing" }