Move docs/ package mirror into document-navigator plugin
Relocate the ~6k-file docs tree from the repo root into plugins/document-navigator/docs/ so the plugin is self-contained and portable. docs/superpowers/ (specs and plans) stays at the repo root. Moved via cp+rm rather than git mv because directory rename() fails with EPERM on this WSL /mnt DrvFs mount; git rename-detection pairs the identical-content files at commit time. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
# @suaveplan/crypto-bin - Suaveplan crypto bins: suaveplan-hash-password (Argon2id / blake2b password hash + verify CLI). Lives in its own package so the universal @suaveplan/crypto does not pull in @suaveplan/cli runtime deps.
|
||||
|
||||
## Summary
|
||||
|
||||
Suaveplan password-hashing CLI. Ships the `suaveplan-hash-password`
|
||||
binary — Argon2id (default) and BLAKE2b password hashing + verification
|
||||
with PHC/MCF-formatted output strings, distinct exit codes per failure
|
||||
class, and an env-injected output adapter so the core is testable
|
||||
without subprocess spawn.
|
||||
|
||||
This package lives separately from `@suaveplan/crypto` so the
|
||||
universal crypto façade does not pull CLI runtime deps into
|
||||
browser/server consumers that just want primitives.
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
## Documentation tree
|
||||
|
||||
- [bin](./src/bin/hash-password.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [hash-password](./src/bin/hash-password.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [hash-password](./src/hash-password/hash-password.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [hash-password](./src/hash-password/hash-password.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
<!-- end:auto-docs --> - [hash-password](./src/bin/hash-password.md) — <!-- begin:auto-docs --> _(no submodules)_- [hash-password](./src/hash-password/hash-password.md) — <!-- begin:auto-docs --> _(no submodules)_- [hash-password](./src/hash-password/hash-password.md) — <!-- begin:auto-docs --> _(no submodules)_- [hash-password](./src/bin/hash-password.md) — <!-- begin:auto-docs --> _(no submodules)_- [hash-password](./src/hash-password/hash-password.md) — <!-- begin:auto-docs --> _(no submodules)_- [hash-password](./src/hash-password/hash-password.md) — <!-- begin:auto-docs --> _(no submodules)_- [hash-password](./src/bin/hash-password.md) — <!-- begin:auto-docs --> _(no submodules)_- [hash-password](./src/hash-password/hash-password.md) — <!-- begin:auto-docs --> _(no submodules)_- [hash-password](./src/hash-password/hash-password.md) — <!-- begin:auto-docs --> _(no submodules)_- [hash-password](./src/bin/hash-password.md) — <!-- begin:auto-docs --> _(no submodules)_- [hash-password](./src/hash-password/hash-password.md) — <!-- begin:auto-docs --> _(no submodules)_ - [hash-password](./src/hash-password/hash-password.md) — <!-- begin:auto-docs --> _(no submodules)_
|
||||
## Quickstart
|
||||
|
||||
```bash
|
||||
# Hash a password (Argon2id by default)
|
||||
$ suaveplan-hash-password --password "correct horse battery staple"
|
||||
$argon2id$v=19$m=65536,t=3,p=1$<salt>$<hash>
|
||||
|
||||
# Verify (exit 0 = match, 1 = mismatch)
|
||||
$ suaveplan-hash-password --password "correct horse battery staple" \
|
||||
--verify '$argon2id$v=19$m=65536,t=3,p=1$<salt>$<hash>'
|
||||
$ echo $?
|
||||
0
|
||||
```
|
||||
|
||||
## Algorithms
|
||||
|
||||
- **`--algo argon2id`** (default) — OWASP 2023-recommended password hash.
|
||||
Output prefix `$argon2id$v=19$...`.
|
||||
- **`--algo blake2b`** — opt-in alternative for environments that need
|
||||
it. Output prefix `$blake2b$v=1$...`. Cost factor is configurable via
|
||||
`--cost-factor <n>` (1–31).
|
||||
|
||||
The verify mode auto-detects the algorithm from the stored hash's prefix,
|
||||
so callers do not have to track which algorithm was used at hash time.
|
||||
|
||||
## Exit codes
|
||||
|
||||
| Code | Meaning |
|
||||
|------|------------------------------------------------------------|
|
||||
| 0 | Success / verify matched |
|
||||
| 1 | Verify mismatch (wrong password) |
|
||||
| 2 | Bad arguments (missing/malformed flag value) |
|
||||
| 3 | Unknown algorithm (unrecognised `--algo` or stored prefix) |
|
||||
| 4 | Verify failed (stored hash is corrupt or unparseable) |
|
||||
|
||||
The `0` / `1` split matches the de-facto contract for shell pipelines —
|
||||
`if suaveplan-hash-password --password ... --verify ...; then ...; fi`
|
||||
works as expected, with `3+` reserved for operator errors so callers can
|
||||
distinguish "wrong password" from "stored data is broken".
|
||||
|
||||
## Programmatic use
|
||||
|
||||
```ts
|
||||
import { main } from "@suaveplan/crypto-bin";
|
||||
|
||||
const out: string[] = [];
|
||||
const err: string[] = [];
|
||||
const code = main(
|
||||
["--password", "pw", "--algo", "blake2b", "--cost-factor", "10"],
|
||||
{
|
||||
write: (s) => out.push(s),
|
||||
writeError: (s) => err.push(s),
|
||||
},
|
||||
);
|
||||
|
||||
if (code === 0) {
|
||||
storeHash(out.join("").trim());
|
||||
}
|
||||
```
|
||||
|
||||
The `main()` function never throws — every error path is captured and
|
||||
surfaced via `env.writeError(...)` and a non-zero return value. See
|
||||
`src/hash-password/hash-password.md` for the full contract.
|
||||
|
||||
## Public surface
|
||||
|
||||
- `main` — testable CLI core.
|
||||
- `parseArgs` — pure argv parser (throws `HashPasswordCliError`).
|
||||
- `detectAlgo` — algorithm sniffer for stored hashes.
|
||||
- `HashPasswordCliEnv` — output adapter interface.
|
||||
- `HashPasswordCliError` — error class wrapping the stable code registry.
|
||||
- `HASH_PASSWORD_CLI_CODES` — `BAD_ARGS` / `UNKNOWN_ALGO` /
|
||||
`VERIFY_FAILED`.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- `@suaveplan/crypto-hash` — Argon2id + BLAKE2b primitives.
|
||||
- `@suaveplan/error` — `SuaveplanError` base + stable code registry.
|
||||
- `@suaveplan/types` — shared cross-package contracts.
|
||||
|
||||
No dependency on `@suaveplan/cli` — argv parsing is hand-rolled (~40
|
||||
lines) so the bin stays small.
|
||||
|
||||
Reference in New Issue
Block a user