first commit
This commit is contained in:
107
docs/security-stack/crypto/crypto-bin/src/bin/hash-password.md
Normal file
107
docs/security-stack/crypto/crypto-bin/src/bin/hash-password.md
Normal file
@@ -0,0 +1,107 @@
|
||||
# `suaveplan-hash-password` bin entry
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
## Purpose
|
||||
|
||||
This file is the platform-runtime entry for the `suaveplan-hash-password`
|
||||
binary shipped by `@suaveplan/crypto-bin`. It is intentionally a minimal
|
||||
shim: it constructs an `HashPasswordCliEnv` adapter from `process.stdout`
|
||||
and `process.stderr`, then delegates to the testable `main()` function in
|
||||
`../hash-password/hash-password.ts`. All argument parsing, algorithm
|
||||
dispatch, and exit-code logic live in that pure core so they can be unit
|
||||
tested by direct invocation rather than by spawning a subprocess.
|
||||
|
||||
The shim exists so the package can publish a Node-style `bin` entry under
|
||||
`./dist/bin/hash-password.js` (with the `#!/usr/bin/env node` shebang
|
||||
preserved by Vite) without coupling the testable core to `process.*`
|
||||
globals. Anything that touches `process.argv` / `process.exit` /
|
||||
`process.stdout` is confined to this module.
|
||||
|
||||
## Features
|
||||
|
||||
- Forwards `process.argv.slice(2)` into `main()` and exits with the
|
||||
returned numeric code.
|
||||
- Wires `process.stdout.write` / `process.stderr.write` into the
|
||||
`HashPasswordCliEnv` adapter — the core never references `process`
|
||||
directly.
|
||||
- Auto-exec guard: only runs `main()` when invoked as the top-level
|
||||
module (`process.argv[1]` ends with `hash-password.js`). Importing this
|
||||
module from a test or another script does not trigger an exit.
|
||||
- Coverage-excluded by design — this module is exercised end-to-end via
|
||||
the bin install path; the logic it wraps is fully covered by
|
||||
`../hash-password/hash-password.test.ts`.
|
||||
- Shebang line emitted verbatim into the dist bundle so the file is
|
||||
directly executable once symlinked by `bun install` / `npm install`.
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```bash
|
||||
# Once installed, the bin is on PATH via the package.json `bin` map
|
||||
$ suaveplan-hash-password --password "correct horse battery staple"
|
||||
$argon2id$v=19$m=65536,t=3,p=1$<salt>$<hash>
|
||||
$ echo $?
|
||||
0
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```bash
|
||||
# Pipe-friendly verify (exit 0 = match, 1 = mismatch, 3+ = error)
|
||||
$ STORED='$argon2id$v=19$m=65536,t=3,p=1$<salt>$<hash>'
|
||||
$ if suaveplan-hash-password --password "$PW" --verify "$STORED"; then
|
||||
> echo "login ok"
|
||||
> else
|
||||
> case $? in
|
||||
> 1) echo "wrong password" ;;
|
||||
> 3) echo "stored hash has unrecognised algorithm" ;;
|
||||
> 4) echo "stored hash is corrupt" ;;
|
||||
> *) echo "argument error" ;;
|
||||
> esac
|
||||
> fi
|
||||
```
|
||||
|
||||
For programmatic invocation that does not spawn a process, import the
|
||||
testable core directly instead of this shim:
|
||||
|
||||
```ts
|
||||
import { main } from "@suaveplan/crypto-bin";
|
||||
const code = main(["--password", "pw"], {
|
||||
write: (s) => process.stdout.write(s),
|
||||
writeError: (s) => process.stderr.write(s),
|
||||
});
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
This module has no public exports — it is a side-effect entry point.
|
||||
Behaviour:
|
||||
|
||||
- On import, registers the auto-exec guard and (if invoked as the
|
||||
top-level script) calls `main(argv, env)` and exits with its return
|
||||
value.
|
||||
- `argv`: `process.argv.slice(2)` — same shape `main()` accepts.
|
||||
- `env.write(s)`: forwards `s` to `process.stdout.write` synchronously.
|
||||
- `env.writeError(s)`: forwards `s` to `process.stderr.write`
|
||||
synchronously.
|
||||
|
||||
For the contract of `main()` itself (exit codes, accepted flags, error
|
||||
classes) see `../hash-password/hash-password.md`.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The auto-exec guard checks `process.argv[1]?.endsWith("hash-password.js")`
|
||||
rather than `import.meta.url === ...` so the same module survives Vite's
|
||||
ES-module bundling without ESM-vs-CJS surprises in older Node hosts. The
|
||||
guard string matches the bundled filename (`hash-password.js`) deliberately
|
||||
— the source is `.ts` and is never executed directly in production.
|
||||
|
||||
`/* istanbul ignore */` markers wrap the guard and the `process.exit`
|
||||
call because the test suite invokes `main()` directly with a captured env
|
||||
adapter (see `../hash-password/hash-password.test.ts`). Spawning a
|
||||
subprocess to cover this two-line wrapper would add filesystem and Node
|
||||
runtime coupling to the test suite without exercising any logic that is
|
||||
not already covered. The `vitest.config.ts` coverage `exclude` list
|
||||
documents this decision in a sibling comment so future readers do not
|
||||
mistake the exclusion for an oversight.
|
||||
Reference in New Issue
Block a user