Skip to content

feat(#40): standalone drop-in PostgREST-compatible CLI#48

Merged
milmazz merged 27 commits into
mainfrom
worktree-cli-implementation
Jul 3, 2026
Merged

feat(#40): standalone drop-in PostgREST-compatible CLI#48
milmazz merged 27 commits into
mainfrom
worktree-cli-implementation

Conversation

@milmazz

@milmazz milmazz commented Jun 8, 2026

Copy link
Copy Markdown
Owner

Summary

Adds a standalone, drop-in PostgREST-compatible CLI for Bier (closes #40), re-scoped from "turn all 26 config CLI cases green" to standalone-runnable Bier + drop-in config compat for the keys Bier actually implements, with an honest conformance disposition for the rest. Design: docs/superpowers/specs/2026-06-07-cli-implementation-design.md; plan: docs/superpowers/plans/2026-06-07-cli-implementation.md.

  • Bier.CLI — a pure, testable run/2 core (%{stdout, stderr, exit} or {:boot, resolved}, no IO/halt) plus a thin escript main/1 + single-instance boot path.
  • Bier.CLI.Config — the PostgREST-dialect ↔ Bier boundary: a single-source-of-truth mapping table (PGRST_* env, kebab keys, aliases, defaults), coerce/2, load/3 (precedence flags > env > file > default, alias resolution, wrong-type→default, shared validation), dump/1 (PostgREST-format, reparse-stable), and to_start_opts/1 (incl. db-uri parsing → discrete connection fields).
  • Bier.CLI.ConfigFilekey = value config-file parser.
  • Shared validators in Bier.Config (jwt-secret length, jwt-aud URI) so Bier.start_link/1 and the CLI reject identically; exact PostgREST messages.
  • Conformance harnessBier.CliCase drives kind: cli cases through the core in-process; new exit_code/dump_contains/stderr_contains/dump_reparse_stable assertions.

Conformance impact

15 of the 26 config CLI cases now pass (1706, 1708–1710, 1712, 1713, 1717, 1719–1723, 1726, 1728, 1730). The remaining 11 keep an explicit pending_reason instead of a parity façade: :cli_parity (full default-table dump 1705, --example 1727), :unmodeled_key (1707, 1711, 1714–1716, 1718, 1729 — keys Bier doesn't implement), :db_config (1724/1725 — DB role-settings source). Recorded in spec/COVERAGE.md.

Standalone packaging (mix release + Dockerfile) and --ready are deferred to #45.

Test plan

  • mix test — 587 tests; the only 4 failures (GeoJSON 1616–1618, RS256 1467) are pre-existing on main (verified against the base commit), not regressions.
  • mix format --check-formatted, mix compile --warnings-as-errors, mix docs --warnings-as-errors, mix hex.audit, mix deps.unlock --check-unused — all clean.
  • escript smoke-tested: mix escript.build && ./bier --dump-config | --version | --help.

🤖 Generated with Claude Code

milmazz and others added 20 commits June 7, 2026 18:07
…le CLI

Re-scopes #40 from "turn all 26 config CLI cases green" to:
standalone-runnable Bier (docker run bier) + drop-in PostgREST-compatible
config (PGRST_* env, kebab keys, config file, PostgREST-format --dump-config)
for the keys Bier actually implements, with an honest conformance disposition
for the rest (:cli_parity / :unmodeled_key / :db_config).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Nine TDD tasks: shared validators, config-file parser, mapping table +
coercion, load/3 precedence, dump/1, run/2 dispatch, escript + to_start_opts,
conformance CLI harness path, and full verification.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds Config.to_start_opts/1 to translate a resolved CLI config map into
Bier.start_link/1 keyword options (parsing db-uri, collapsing
allow-override tx-end variants). Adds Bier.CLI.main/1 as the escript
entry point with a blocking boot path, and wires mix.exs escript config
with app: nil so --dump-config/--version run without a live DB.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…led to CLI config

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…d-clause warnings

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
claude and others added 7 commits July 3, 2026 18:08
Resolves the conformance_test.exs moduledoc conflict: keeps the CLI-case
wording from this branch and drops the :openapi_doc exclusion that main
removed when #39 (OpenAPI document generation) landed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KMemDkesmnvCYJ2ovZGKu5
main now gates CI on mix credo --strict; the multi-alias in Bier.CLI was
the only one in lib/ and trips Consistency.MultiAliasImportRequireUse.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KMemDkesmnvCYJ2ovZGKu5
- Resolve alias-derived env vars (PGRST_DB_SCHEMA, PGRST_MAX_ROWS, ...):
  each key spelling is now a full source consulting its own env var then
  its file key, matching PostgREST's optWithAlias semantics.
- Config-file parser: support end-of-line '#' comments after values,
  keep '#' literal inside quoted strings, and reject trailing garbage or
  an unterminated quote instead of silently mangling the value.
- Print --version/--help before loading config, as PostgREST does, so a
  broken PGRST_* var or missing config file cannot mask them.
- db-uri: accept libpq keyword/value conninfo strings and honor sslmode
  (require/verify-* map to a new ssl start option wired through
  Bier.Config and the Postgrex pool).
- Count jwt-secret length in bytes (PostgREST's BS.length), not graphemes.
- Add openapi-security-active to the CLI spec table and to_start_opts.
- Share the admin-server-port/server-port rule as
  Bier.Config.validate_admin_server_port/2 instead of duplicating it.
- COVERAGE.md: stop claiming 1707 exercises the db-pool aliases; it is
  deferred as :unmodeled_key.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KMemDkesmnvCYJ2ovZGKu5
Advisories published against locked deps (mint/req/plug/bandit today)
were failing the job before compile/credo/docs/test ever ran, hiding
all signal for the change under review. Every gate still runs and the
job still fails on advisories until the deps are updated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KMemDkesmnvCYJ2ovZGKu5
Resolves the conformance_test.exs moduledoc conflict again: keeps the
CLI-case wording and drops the :jwt exclusion that main removed now that
the harness signs JWTs per-case (#41).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KMemDkesmnvCYJ2ovZGKu5
@milmazz
milmazz merged commit d22f8ea into main Jul 3, 2026
3 checks passed
@milmazz
milmazz deleted the worktree-cli-implementation branch July 3, 2026 19:02
milmazz pushed a commit that referenced this pull request Jul 3, 2026
PR #48 (the CLI branch this was stacked on) was squash-merged to main,
so main and this branch both carried the CLI files. Conflicts resolved
by taking main's versions (which include the review-finding fixes) for
everything this branch does not touch; mix.exs keeps the releases()
config on top of main's state.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KMemDkesmnvCYJ2ovZGKu5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[conformance][lib] CLI implementation — 26 pending config cases

2 participants