# Dependency Admission Policy
`base64-ng` defaults to zero external crates in the published package. That is
a security and maintenance choice: Base64 is infrastructure code, and every
new dependency expands the audit, license, advisory, and supply-chain surface.
## Current Status
The non-published `protocol-registry/runner` pins `base64` 0.23.0 and
`base64ct` 1.8.3 solely as independent release-evidence references. Its lock
file, cargo-deny policy, RustSec audit, and license provenance are checked by
`scripts/check-protocol-registry.sh`; neither crate enters a published runtime
dependency graph through this tooling.
- `Cargo.toml` has no normal, build, or dev dependencies.
- `scripts/validate-dependencies.sh` fails if the root crate dependency graph
contains anything beyond `base64-ng` itself.
- `scripts/check_reserved_features.sh` verifies that `tokio`, `kani`, and
`fuzzing` remain inert and dependency-free until admitted, and that deferred
integration features such as `serde`, `bytes`, `zeroize`, `subtle`, and
`criterion` are not exposed before dependency admission.
- `allow-wasm32-best-effort-wipe` is a dependency-free policy feature, not a
dependency admission. It is required to build for `wasm32`, where cleanup is
limited to a compiler-fence-only wipe barrier.
- `allow-compiler-fence-only-wipe` is a dependency-free policy feature, not a
dependency admission. It is required to build unsupported native architectures
that do not have a `base64-ng` hardware wipe barrier and therefore fall back
to compiler-fence-only cleanup.
- `base64_ng_aarch64_csdb_attested` is a dependency-free custom cfg operator
attestation, not a dependency admission and not a Cargo feature. It should
only be enabled after the deployment has evidence that the target AArch64
core treats CSDB as an effective speculation barrier for the CT result gate.
Builds that set it report `hardware-speculation-barrier-build-asserted` so
audit logs preserve the operator-attestation boundary.
- `base64-ng-sanitization` is an optional companion package for applications
that already admit `sanitization`; it is not a dependency of the core
`base64-ng` package. Its `2.0.0` line requires an exact
`sanitization` `=2.0.3` dependency
so callers can use `sanitization::ct::Choice`, native
constant-time-oriented equality helpers, and opt-in locked-secret fill APIs
without adding dependencies to the core crate. Release review must verify
the crates.io owner set for `sanitization` before publishing companion
updates because that crate sits directly in the optional secret-cleanup
dependency chain.
Military, hermetic, or otherwise high-assurance deployments should vendor
the exact locked source, retain the registry checksum, and require an
independent review before updating that vendored copy. This operational
control is additive to Cargo's checksum, RustSec, license, and source-policy
checks.
- `base64-ng-derive` is an optional dependency-free companion for fixed-size
2.0 `SecretArray<N>` newtypes. Its macro requires explicit sealed-codec,
padding, exact-length, and exposure policy and does not add proc-macro
machinery to the core `base64-ng` package.
- `base64-ng-serde`, `base64-ng-bytes`, `base64-ng-subtle`, and
`base64-ng-tokio` are optional companion packages for applications that
already admit `serde`, `bytes`, `subtle`, or `tokio`; they are not
dependencies of the core `base64-ng` package.
- `base64-ng-mime` is a dependency-minimal protocol companion. Its only
runtime dependency is the matching `base64-ng` package. Python's standard
`email.base64mime` and the system OpenSSL command are test-time
interoperability references and are not package dependencies.
- `base64-ng-multibase` is a dependency-minimal protocol companion. Its only
runtime dependency is the matching `base64-ng` package. The multiformats
registry and official vectors are hash-locked repository evidence, while
Python's standard `base64` module is a test-time interoperability reference;
none are package dependencies.
- `base64-ng-password` is a dependency-minimal format companion. Its only
runtime dependency is the matching `base64-ng` package. Python's standard
Base64 module and the system OpenSSL command are test-time interoperability
references, not package dependencies; final source and implementation pins
belong to Commit 49.
- `base64-ng-openpgp` is a dependency-minimal protocol companion. Its only
runtime dependency is the matching `base64-ng` package. GnuPG and Sequoia
`sq` are test-time interoperability references, while the locked RFC 9580
source and errata remain repository evidence; none are package dependencies.
- `base64-ng-pem` is a dependency-minimal protocol companion. Its only
runtime dependency is the matching `base64-ng` package. Python `ssl` and
the system OpenSSL command are test-time RFC 7468 interoperability
references and are not package dependencies.
- Fuzz, performance, and dudect-style timing harness dependencies are isolated
under `fuzz/`, `perf/`, and `dudect/`; the standard local gate checks them
separately from the published crate dependency graph.
- CI toolchain setup requires `rustup` and `cargo` from the runner image. The
repository script intentionally refuses unauthenticated `curl | sh` rustup
bootstrap during CI; missing toolchain managers are treated as infrastructure
failures, not as a reason to execute freshly downloaded shell installers.
## v1.0 Final Admission Review
The `v1.0` release keeps the core `base64-ng` package dependency-free.
Optional ecosystem integrations may be admitted only as separate companion
crates with their own dependency review and release checks.
Current decisions:
- `base64-ng-sanitization` is admitted as a companion crate because it keeps the
core package dependency-free while giving applications that already use
`sanitization` a direct CT decode path into clear-on-drop secret containers.
Its optional `high-assurance` feature admits `sanitization` memory locking,
strict random canaries, and strict assembly comparison so supported x86_64
and AArch64 native deployments can decode directly into locked mappings
through `LockedSecretBytes` or `LockedSecretVec`.
- `base64-ng-derive` is admitted as a companion crate because it keeps
proc-macro code and generated newtype ergonomics outside the core package.
Its 2.0 surface is intentionally limited to one private `SecretArray<N>`
tuple field and four mandatory policy keys. It has no external dependency
and generates no implicit exposure or equality traits.
- `base64-ng-serde` is admitted as a companion crate because serialization
remains explicit at the field boundary and does not hide alphabet or padding
choices inside the core package.
- `base64-ng-bytes` is admitted as a companion crate because services that
already use `bytes` can opt into `Bytes`, `Buf`, and `BufMut` helpers without
adding `bytes` to the core package.
- `base64-ng-subtle` is admitted as a companion crate because authentication,
MAC, password-hash, and token verification boundaries can opt into a reviewed
`subtle::ConstantTimeEq` primitive without adding `subtle` to the core
package. Its 2.0 trait is sealed to the final secret owners and views, names
public-length behavior, and returns `Choice` without boolean convenience
sugar.
- `base64-ng-tokio` is admitted as a companion crate for async read-all/write-all
helpers, including caller-limited variants for peer-controlled request or
frame boundaries, and manual `AsyncRead`/`AsyncWrite` streaming adapters with
fixed buffers and drop cleanup. Writer adapters finalize pending Base64 tails
during `AsyncWrite::poll_shutdown`; callers must drive shutdown to completion
before extracting the wrapped writer. It enables only Tokio `io-util` and
`rt`: `rt` is required for cooperative budget consumption between bounded
collection, transformation, and delivery chunks.
- `base64-ng-imap` is admitted as a companion because the obsolete RFC 3501
modified-Base64 payload is legacy protocol grammar rather than core RFC 4648
behavior. It depends only on the core crate, requires finite limits, accepts
already-converted UTF-16BE bytes, and does not claim complete mailbox or
Unicode conversion support.
- `base64-ng-mime` is admitted as a companion because RFC 2045's permissive
content-transfer body rules are protocol grammar, not a reason to weaken
strict RFC 4648 core defaults. It has finite input/output/line/skip/work
limits and does not claim complete MIME message or header parsing.
- `base64-ng-multibase` is admitted as a companion because its leading prefix
and evolving external registry are protocol metadata rather than core RFC
4648 behavior. It admits only the four pinned Base64-family entries, applies
finite limits, and does not claim complete multibase support.
- `base64-ng-password` is admitted as a companion because Passlib PBKDF2 and
SHA-crypt add record grammar and algorithm-specific checksum permutations
beyond generic Base64. It depends only on the core crate, applies finite
limits and redacted formatting, and exposes no hashing or verification API.
- `base64-ng-openpgp` is admitted as a companion because armor boundaries,
headers, checksum status, block types, and closing-tail validation are
protocol grammar beyond core Base64. It has finite limits and does not claim
packet parsing or cleartext-signature support.
- `base64-ng-pem` is admitted as a companion because RFC 7468 labels,
encapsulation boundaries, adjacent text, multi-block documents, and parser
latitude are protocol grammar rather than core Base64 behavior. It has
finite limits, rejects legacy encapsulated headers, and never claims ASN.1
payload validation.
- The core `tokio` feature remains reserved and inert by design. The async
cancellation, drop cleanup, chunk-boundary, dependency, and release-evidence
requirements have been satisfied for `base64-ng-tokio`; moving Tokio into
the core crate would require a separate dependency admission review.
- `zeroize` remains deferred for the core crate; applications can combine their
own approved dependencies with caller-owned buffers while `base64-ng` keeps
its audited local best-effort helpers dependency-free.
- `subtle` is admitted only through `base64-ng-subtle`, not through the core
crate.
- Property-testing and benchmark frameworks remain isolated or deferred; fuzz,
dudect-style timing, and performance harnesses stay outside the published
crate package.
## Admission Requirements
Before adding any dependency to the published crate, the change must document:
- Why `core`, `alloc`, or `std` is not sufficient.
- Whether the dependency is runtime, build-time, dev-only, feature-gated, or
tool-only.
- The full transitive dependency graph.
- License compatibility with `MIT OR Apache-2.0`.
- RustSec advisory status and yanked-release status.
- Whether the dependency works under the crate's supported `no_std` feature
combinations.
- Whether the dependency changes MSRV, build reproducibility, or target support.
- How the dependency is disabled for users who do not need the feature.
The release gate must remain clean after the change:
```sh
scripts/checks.sh
scripts/stable_release_gate.sh release
```
At minimum, evidence must include:
- `cargo tree` for the affected feature set.
- `cargo deny check`.
- `cargo audit`.
- `scripts/check_scheduled_advisories.sh` through the daily and manually
dispatchable security-audit workflow.
- `cargo license --json`.
- Updated release notes and migration/security documentation when the public
API or threat model changes.
## Default Rejections
The following are rejected unless a specific review proves they are necessary:
- Helper crates for small bit manipulation, table generation, feature
selection, error formatting, or simple CLI behavior.
- Git dependencies.
- Default-feature runtime dependencies.
- Dependencies with unclear licensing, unmaintained status, active security
advisories, yanked releases, or unnecessary transitive graphs.
## Deferred Core Integrations
The following integrations are intentionally not admitted in the published
core crate today:
- `tokio`: the core feature remains reserved and inert. Use `base64-ng-tokio`
for the admitted read-all/write-all helper surface and reader/writer
streaming adapters. Prefer caller-limited helpers for peer-controlled input.
- `serde`: use `base64-ng-serde` when explicit serialization wrappers or
field-level modules for Standard, URL-safe, MIME, or PEM profiles are
needed. The core crate does not admit `serde`.
- `bytes`: use `base64-ng-bytes` when `Bytes`, `Buf`, or `BufMut` integration
is needed. The core crate does not admit `bytes`.
- `zeroize`: deferred unless a review proves that the dependency materially
improves the documented best-effort cleanup posture beyond the current
audited local helpers.
- `subtle`: use `base64-ng-subtle` when protocol code needs the sealed reviewed
equality boundary for final 2.0 secret owners and views. Length mismatch is
public and `Choice` declassification remains explicit.
- Criterion or other benchmark frameworks: keep benchmark evidence isolated
unless the added dependency graph clearly improves release evidence quality.
These are product decisions as much as technical ones. The crate is allowed to
remain smaller than the broader ecosystem when dependency-free APIs preserve
explicit security semantics.
Downstream applications may still combine `base64-ng` with their own approved
dependencies. For example, a service with an existing `zeroize` policy can
decode into a caller-owned buffer with `decode_slice_clear_tail` and then call
`Zeroize::zeroize()` on that buffer after the protocol step is complete. That
keeps the published `base64-ng` crate dependency-free while allowing the
application to apply its local memory-cleanup policy at the ownership boundary.
This is the recommended pattern for deployments that require a dependency-backed
zeroization policy while still wanting `base64-ng` itself to remain a small,
auditable zero-runtime-dependency crate.
## Isolated Tooling
Fuzzing, benchmark, and timing-evidence dependencies may live in isolated
workspaces only when they are not packaged with the published crate:
- `fuzz/` dependencies are reviewed by `scripts/check_fuzz.sh`.
- `perf/` dependencies are reviewed by `scripts/check_perf.sh`.
- `dudect/` dependencies are reviewed by `scripts/check_dudect.sh`.
- `crates/base64-ng-sanitization/`, `crates/base64-ng-derive/`,
`crates/base64-ng-serde/`, `crates/base64-ng-bytes/`,
`crates/base64-ng-subtle/`, `crates/base64-ng-tokio/`,
`crates/base64-ng-imap/`, `crates/base64-ng-mime/`,
`crates/base64-ng-multibase/`, `crates/base64-ng-password/`,
`crates/base64-ng-openpgp/`, and `crates/base64-ng-pem/` are optional companion crates, not dependencies of
the core `base64-ng` package. They are reviewed separately by
`scripts/check_companion_crates.sh` so the root package keeps its
zero-runtime-dependency guarantee.
- `packages/base64-ng-wasm-loader/` is an npm companion with zero JavaScript
dependencies. Its private Rust artifact build depends only on the matching
local `base64-ng` source. `npm ci`, path-independent deterministic artifact
rebuilds, embedded SHA-256 verification, checkout-path leakage rejection,
exact tarball inspection, and install-from-package tests run through
`scripts/check-2.0-wasm-loader.sh`.
`scripts/checks.sh` runs those isolated harness checks so ordinary local
verification catches harness dependency drift before release-only evidence
steps.
Those isolated dependencies do not weaken the zero-dependency guarantee for the
published core crate.