Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Fixed
- `rc0 acme zone-exists` now hits `GET /api/v1/acme/zones/{zone}`, the
current upstream path. RcodeZero moved the endpoint from
`/api/v1/acme/{zone}` to `/api/v1/acme/zones/{zone}` (consistent with
the sibling `/zones/{zone}/rrsets`), which broke the command against
the live API. Pinned `tests/fixtures/openapi.json` refreshed from the
live spec, integration tests rewired to the new path, and the nightly
spec-drift workflow is green again. Closes #15.
- `scripts/gen_api_coverage.py`: corrected stale `rc0 record` verb
mapping (`add / update / replace-all` → `set / append / import`) that
predated the v1.0 rename, so regenerated `docs/api-coverage.md` no
longer regresses to the old names.

## [2.1.1] — 2026-05-01

### Changed
Expand Down
2 changes: 1 addition & 1 deletion docs/api-coverage.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ Generated from pinned OpenAPI spec v2.9.

| Status | Method | Endpoint | CLI Command | Notes |
|--------|--------|----------|-------------|-------|
| ✅ | `GET` | `/api/v1/acme/zones/{zone}` | `rc0 acme zone-exists` | |
| ✅ | `GET` | `/api/v1/acme/zones/{zone}/rrsets` | `rc0 acme list-challenges` | |
| ✅ | `PATCH` | `/api/v1/acme/zones/{zone}/rrsets` | `rc0 acme add-challenge / remove-challenge` | |
| ✅ | `GET` | `/api/v1/acme/{zone}` | `rc0 acme zone-exists` | |
| ✅ | `GET` | `/api/v2/messages` | `rc0 messages poll` | |
| ✅ | `GET` | `/api/v2/messages/list` | `rc0 messages list` | |
| ✅ | `DELETE` | `/api/v2/messages/{id}` | `rc0 messages ack` | |
Expand Down
2 changes: 1 addition & 1 deletion docs/rc0-cli-mission-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ The CLI must expose **all** of the following. Endpoints marked `[DEPRECATED]` ar

| Endpoint | Command |
|---|---|
| `/api/v1/acme/{zone}` GET | `rc0 acme zone-exists` |
| `/api/v1/acme/zones/{zone}` GET | `rc0 acme zone-exists` |
| `/api/v1/acme/zones/{zone}/rrsets` GET | `rc0 acme list-challenges` |
| `/api/v1/acme/zones/{zone}/rrsets` PATCH | `rc0 acme add-challenge` / `rc0 acme remove-challenge` |

Expand Down
6 changes: 3 additions & 3 deletions scripts/gen_api_coverage.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
# Full endpoint → CLI command mapping (extends contract test map with mutations)
ENDPOINT_TO_COMMAND: dict[tuple[str, str], tuple[str, ...]] = {
# ACME (v1)
("GET", "/api/v1/acme/{zone}"): ("acme", "zone-exists"),
("GET", "/api/v1/acme/zones/{zone}"): ("acme", "zone-exists"),
("GET", "/api/v1/acme/zones/{zone}/rrsets"): ("acme", "list-challenges"),
("PATCH", "/api/v1/acme/zones/{zone}/rrsets"): ("acme", "add-challenge / remove-challenge"),
# Messages
Expand Down Expand Up @@ -73,8 +73,8 @@
("POST", "/api/v2/zones/{zone}/outbound"): ("zone", "xfr-out", "set"),
("DELETE", "/api/v2/zones/{zone}/outbound"): ("zone", "xfr-out", "unset"),
("GET", "/api/v2/zones/{zone}/rrsets"): ("record", "list"),
("PATCH", "/api/v2/zones/{zone}/rrsets"): ("record", "add / update / delete / apply"),
("PUT", "/api/v2/zones/{zone}/rrsets"): ("record", "replace-all"),
("PATCH", "/api/v2/zones/{zone}/rrsets"): ("record", "set / append / delete / apply"),
("PUT", "/api/v2/zones/{zone}/rrsets"): ("record", "import"),
("DELETE", "/api/v2/zones/{zone}/rrsets"): ("record", "clear"),
("POST", "/api/v2/zones/{zone}/retrieve"): ("zone", "retrieve"),
("POST", "/api/v2/zones/{zone}/sign"): ("dnssec", "sign"),
Expand Down
4 changes: 2 additions & 2 deletions src/rc0/api/acme.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@


def zone_exists(client: Client, zone: str) -> list[str]:
"""GET /api/v1/acme/{zone} — returns ["found"] if configured."""
response = client.get(f"/api/v1/acme/{zone}")
"""GET /api/v1/acme/zones/{zone} — returns ["found"] if configured."""
response = client.get(f"/api/v1/acme/zones/{zone}")
result: list[str] = response.json()
return result

Expand Down
2 changes: 1 addition & 1 deletion src/rc0/commands/acme.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def _acme_client(state: AppState) -> Generator[Client]:

@app.command("zone-exists")
def zone_exists_cmd(ctx: typer.Context, zone: ZoneArg) -> None:
"""Check if a zone is configured for ACME. API: GET /api/v1/acme/{zone}
"""Check if a zone is configured for ACME. API: GET /api/v1/acme/zones/{zone}

Examples:

Expand Down
2 changes: 1 addition & 1 deletion tests/fixtures/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -3243,7 +3243,7 @@
"deprecated": false
}
},
"/api/v1/acme/{zone}": {
"/api/v1/acme/zones/{zone}": {
"get": {
"tags": [
"API: ACME"
Expand Down
4 changes: 2 additions & 2 deletions tests/integration/test_acme_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,15 @@ def _invoke(cli: CliRunner, *args: str, input: str | None = None) -> object:

@respx.mock
def test_zone_exists_found(cli: CliRunner, isolated_config: Path) -> None:
respx.get(f"{_BASE_V1}/{_ZONE}").mock(return_value=httpx.Response(200, json=["found"]))
respx.get(f"{_BASE_V1}/zones/{_ZONE}").mock(return_value=httpx.Response(200, json=["found"]))
r = _invoke(cli, "acme", "zone-exists", _ZONE)
assert r.exit_code == 0, r.output
assert json.loads(r.output) == ["found"]


@respx.mock
def test_zone_exists_not_found(cli: CliRunner, isolated_config: Path) -> None:
respx.get(f"{_BASE_V1}/{_ZONE}").mock(
respx.get(f"{_BASE_V1}/zones/{_ZONE}").mock(
return_value=httpx.Response(404, json={"message": "not found"})
)
r = _invoke(cli, "acme", "zone-exists", _ZONE)
Expand Down
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading