Skip to content

claude-code-chat-browser: Enforce debug/host guard, versioning policy, and API response stability docs #58

@clean6378-max-it

Description

@clean6378-max-it

Planned Effort

9 story points (one PR) — combines sprint items #3 + #5 + #6:

Sprint item Points Topic
#3 3 Programmatic guard: refuse --debug with non-loopback --host
#5 3 __version__, CHANGELOG.md, deprecation policy
#6 3 API response shape contract (stable vs experimental fields)

Out of scope this issue: removing export_count (Thursday #4 — requires this policy first).

Problem

  1. Security gap: Week 4 made --debug opt-in (default=False) and documented the 0.0.0.0 + debug risk in the README, but the process still allows that dangerous combination.
  2. No release contract: There is no __version__, no CHANGELOG.md, and no documented deprecation process — so API fields (e.g. duplicate export_count on /api/export/state) cannot evolve safely.
  3. Hyrum's Law: The SPA reads every JSON field it sees; without documented stable vs experimental fields, accidental coupling blocks refactors.

Goal

One merged PR that:

  1. Fails fast when --debug is used with a non-loopback --host.
  2. Establishes versioning + deprecation policy for future API changes.
  3. Documents response field stability for key endpoints (especially export state before Thursday's alias cleanup).

Scope

A — Debug + non-loopback host guard (3 pt)

Touch points: app.py, tests/test_cli_args.py, README.md (one-line cross-link)

  • Add is_loopback_host(host: str) -> bool (module-level in app.py or utils/cli_hosts.py if you prefer zero test duplication):

    • Accept: 127.0.0.1, localhost, ::1 (normalize case for hostnames).
    • Reject: 0.0.0.0, empty string, public/LAN IPs.
  • In if __name__ == "__main__": after parse_args():

    if args.debug and not is_loopback_host(args.host):
        print(
            "error: --debug is only allowed with a loopback --host "
            "(127.0.0.1, localhost, or ::1). "
            "Binding to a non-loopback address with debug exposes the Werkzeug "
            "interactive debugger on the network.",
            file=sys.stderr,
        )
        raise SystemExit(1)
  • Tests (tests/test_cli_args.py or tests/test_cli_host_guard.py):

    • 127.0.0.1 + --debug → guard does not exit (smoke via calling is_loopback_host + guard helper, or subprocess if already used elsewhere).
    • 0.0.0.0 + --debugSystemExit(1).
    • 0.0.0.0 without --debug → allowed.
  • README: add one sentence under existing security warning that the server refuses the bad combo at startup.

B — Versioning + CHANGELOG + deprecation policy (3 pt)

Touch points: app.py (or new version.py), CHANGELOG.md, CONTRIBUTING.md or docs/deprecation-policy.md, README.md

  • Add canonical __version__ = "0.1.0" (importable from app for future /api/version if desired — not required this issue).
  • Create CHANGELOG.md (Keep a Changelog format):
    • ## [0.1.0] - 2026-06-02 (or merge date)
    • Sections: Added (version file, policy, guard), Changed (docs), Deprecated (none yet — note export_count planned).
  • Document deprecation policy (minimum):
    • Deprecated fields stay for at least one release with docs + CHANGELOG notice.
    • SPA (static/js/*.js) must migrate before field removal.
    • Prefer last_export_session_count over export_count for new code.
  • Link policy from CONTRIBUTING.md and README.

C — API response shape contract (3 pt)

Touch points: docs/api-reference.md, optional docs/api-stability.md

Extend documentation for at least these responses:

Endpoint Why
GET /api/export/state export_count alias + Thursday cleanup
GET /api/projects (list) SPA projects page
GET /api/projects/<name>/sessions/<id> (session payload) Drives sessions.js

For each documented response table, add a Stability column:

Value Meaning
stable Will not rename/remove without deprecation period
experimental May change without major version bump
deprecated Still present; removal scheduled (link CHANGELOG)

Document one migration approach (pick one, document clearly):

  • Additive default: new field → deprecate old → remove after policy period, or
  • Future /api/v2/... for breaking changes (no implementation required this week).

Do not remove export_count in this PR — only mark it deprecated in docs.

Acceptance Criteria

  • app.py exits with clear error on --host 0.0.0.0 --debug (and similar non-loopback hosts)
  • Tests cover loopback-allowed and non-loopback-refused cases
  • __version__ exists; CHANGELOG.md has initial release entry
  • Deprecation policy documented and linked from CONTRIBUTING/README
  • docs/api-reference.md marks stable / experimental / deprecated fields for export state + at least two other key endpoints
  • pytest -q and mypy pass; npm test unchanged/green

Metadata

Metadata

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions