- CLI: enroll, run, status, version, help (core.Main with a role
factory); the agent binaries use a placeholder factory until the
BIND and Kea roles are wired in.
- Enrollment: local ECDSA P-256 key and CSR, TLS 1.3 to the agent API
with the server chain pinned to the CA fingerprint.
- ServerSource: mTLS gRPC with keepalive, Connect stream (Hello,
Welcome, heartbeats, apply and renew commands), reconnect with
exponential backoff and jitter, GetDesiredState polling as fallback,
certificate renewal after half of the lifetime.
- Apply pipeline: fetch, bundle verification with replay protection,
store, Validate, Activate, Health with retries, rollback to the last
good revision; outcomes succeeded/rejected/rolled_back/failed are
queued in state.json and reported; failed revisions are retried only
by a newer revision or an explicit push.
- Lease reporting with change detection, persistent sequence and full
snapshots at start, per connection and periodically.
- Tests with fake roles, a fake source and an in-process fake
AgentService over real mTLS.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent configuration (agent-<role>.yaml, strict decoding, role section
passed undecoded to the role factory) and the state directory of ADR
0011: identity with interrupted-renewal recovery, verified revisions
under revisions/<n>/, state.json with apply results, lease sequence and
queued deployment reports, atomic writes, pruning and a lock file.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent overview with connection, health and revision state (polled every
five seconds until the live stream of M4), agent details with checks and
deployment history, enrollment token dialog showing the ready-to-run
command, revision list and creation, revision details with deployments
and files, and a lease list with network, state and text filters.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Shared Apache-2.0 packages for the signed bundle format and the agent
certificate conventions, the agent role interface, REST API spec for
agents, enrollment tokens, revisions, deployments and leases, and ADR
0021. Generator settings now hold the target paths on the managed hosts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- stable Kea subnet IDs per network (migration 00002)
- generator settings (SOA, name servers, TTLs, recursion, DHCP defaults)
- GET /config/preview renders the configuration for the current data
- UI: configuration preview page and DNS/DHCP settings page
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- configgen: input model shared by derivation and renderers
- derive: forward zones per domain, reverse zones (IPv4 octet, IPv6 nibble
boundaries), A/AAAA/PTR from static and manual_dhcp entries, Kea subnets
with effective pools and reservations; pure and deterministic
- bindgen: zone-statement include, options include, zone files with strict
validation, canonical ordering and RFC 1035 TXT escaping
- keagen: typed Kea DHCPv4 JSON with strict validation
- golden-file, validation, determinism and fuzz tests
- integration tests check generated files with real named-checkconf,
named-checkzone (BIND 9.18, 9.20) and kea-dhcp4 -t (Kea 2.6, 3.2);
new CI job
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- end-to-end OIDC test: discovery, PKCE (S256) verified by the IdP, nonce,
state cookie, ID token signature, user creation, role sync, refused
login without role, forged state
- make run-server / dev-admin with deploy/config/server.dev.yaml
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Creates the product and the standard policy in Keygen (one server per
license, license-key activation, daily heartbeat), issues licenses with
limits in metadata and writes offline license files. The admin token is
only read from the environment.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- login with TOTP step and SSO button, forced password change, account
page with password change and TOTP setup (QR code)
- layout with permission-based navigation, license banner, theme/language
- networks: list with utilization, create/edit with pool editor, detail
page with address map
- addresses: server-side filtered/sorted, virtualized table, inline type
switch with DNS/DHCP preview, bulk actions, saved filters, CSV import
(dry run first) and export
- license, users, audit log and OIDC settings pages
- typed API client from the OpenAPI spec; errors translated by code
- German default, English second language
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- route the UI as "/" (GET/HEAD only) to avoid a ServeMux conflict with /api/
- constraint violations carry their specific top-level code
- MAC search accepts '-' and '.' separators
- CSV import reports syntax and validation problems in one pass
- license write lock is evaluated against the clock on every request
- enabling TOTP keeps the consumed time step (no replay of the setup code)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- commands: serve, migrate, bootstrap-admin, gen-master-key
- /metrics with route-pattern labels and license gauge, /readyz checks DB
- fix OpenAPI flow mappings with commas; generate TypeScript API types
(openapi-typescript) and check them in CI
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- one route table with access level, permission and write flag
- session cookie auth, MFA and forced password change gates, CSRF token
plus Origin/Sec-Fetch-Site checks, license read-only lock
- RFC 9457 problem responses with stable codes and field problems
- OIDC authorization code flow with PKCE, state cookie and nonce
- contract tests: spec valid, routes == spec, every request/response in
the API tests validated against the spec
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- every mutation writes its audit entry in the same transaction
- stable error codes; constraint violations mapped to field problems
- bulk changes and CSV import are all-or-nothing, using savepoints so that
all problems are reported at once
- CSV export neutralizes spreadsheet formulas
- OIDC settings with encrypted client secret, role mapping from claims
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- every Keygen response is verified: Ed25519 signature over request target,
host, date and digest; body digest; date freshness; validation nonce
- machine activation by HMAC-based fingerprint, entitlements, heartbeats
- offline license files (base64+ed25519, aes-256-gcm+ed25519)
- pure state evaluation trial -> valid <-> grace -> read_only with one grace
period for unreachable, suspended and expired licenses
- encrypted cache, periodic revalidation; account ID and public key are
embedded at build time
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Server-side filtering/sorting/pagination with whitelisted sort keys, usage
aggregation in SQL, optimistic locking, FQDN maintenance on domain change.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- config: YAML file plus environment overrides, day durations, validation
- secrets: AES-256-GCM keyring with key IDs, AAD binding and rotation
- store: pgx pool, embedded goose migrations with downgrade protection,
initial schema with overlap/containment/uniqueness constraints
- storetest: per-test schemas; CI runs them against a PostgreSQL service
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The pattern meant for Go test binaries also matched db.dev.test, so BIND in
CI started without the forward zone.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The fixed 172.30.53.0/24 subnet collided with an existing network on the
CI runner's Docker host. Seed data now uses 192.0.2.0/24 (RFC 5737), served
by Kea via relay; host ports are configurable and random in CI, and each
CI run uses its own compose project.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Pinned actions by commit SHA, checksum-verified tool installation,
release upload via the Gitea API (idempotent, dry-run capable).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bind mounts break when the Docker daemon does not share the job's
filesystem, as with containerised CI runners.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
BIND uses the production layout (single include under ddi-suite/).
Smoke test checks queries, zone validity, refused recursion and Kea config.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
German default with English as second language (i18next), light/dark/system
theme, server health indicator. ESLint (strict type-checked), Prettier,
Vitest. Product name injected at build time.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- internal/brand: central product, binary and path names (ldflags-overridable)
- internal/buildinfo, internal/logging (slog, secret redaction)
- server: env config, HTTP server with /healthz, /readyz, request IDs,
access log, panic recovery, security headers, graceful shutdown
- web: embedded SPA handler with fallback page when UI is not built
- agent: ddi-agent-dns and ddi-agent-dhcp binaries on a shared core CLI
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>