IdempotencyKey middleware caches POST responses by Idempotency-Key
header for 24h. Prevents duplicate registrations from network retries.
Returns X-Idempotency-Replayed: true on cached responses.
Commit #102.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All 6 Mod modules now register API routes via ApiRoutesRegistering
instead of WebRoutesRegistering with CSRF hacks. The api middleware
group (ThrottleRequests + SubstituteBindings, no CSRF/session)
handles everything natively. Website/Api module simplified to just
metrics and homepage. fireApiRoutes() added to Web Boot.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- UpdateDnsRecords Action: controller method now one-liner, all DNS
logic in Action with activity logging and edit lock.
- Prometheus metrics at /v1/metrics: chain_height, alias_count,
claims_pending, dns_tickets, gateways_live. Grafana-ready.
- ValidateJsonRequest middleware: enforces application/json on POST,
64KB body size limit. Applied to all /v1/* API routes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
chain:stop sends SIGTERM and waits for graceful shutdown.
DNS updateRecords now logs 'dns_updated' activity with ticket_id
and records. Claim approve/reject also logged in previous commit.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ChainService (code=chain, no deps) and NamesService (code=names,
depends on chain). Ready for CorePHP service registry discovery
when core-api package is installed.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
DomainScope middleware checks Host header per-request — Octane-safe.
Applied to Api homepage (scoped to api.lthn.io). Explorer and Docs
subdomain routes stay disabled — catch-all routes like /{section}/{page?}
match before middleware runs, breaking other routes. These modules
need own containers for proper domain isolation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
DaemonRpc implements ChainDaemon, WalletRpc implements ChainWallet.
Interfaces bound in FrameworkBooted — enables mocking for tests and
swapping to Go wrapper when go-process is ready. Concrete bindings
kept for backwards compatibility.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CorePHP manages the testnet chain binaries via ConsoleBooting lifecycle.
chain:start checks if daemon/wallet are running, starts them if not,
waits for RPC readiness. chain:status shows daemon height, aliases,
PoS status, wallet and LNS node state. Config-driven paths for
binary locations, data dirs, mining address.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
DaemonRpc, WalletRpc singletons and config now register in
FrameworkBooted instead of WebRoutesRegistering. Per CorePHP docs,
service registration belongs in FrameworkBooted. Controller DI
resolves lazily so singletons don't need to exist during route
registration. Verified health endpoint still works.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Production stack has honeypot that null-routes API payloads sent to
the web domain. API routes now only register via Website/Api module
(api.lthn.io). Mod modules stripped to web-only routes. Frontend JS
fetch calls use configurable API_URL for cross-origin API access.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All 6 Mod modules now use $event->routes() and $event->views() instead
of raw Route:: and app('view')-> calls. Service singletons moved to
FrameworkBooted where appropriate. Website/Api module added for
api.lthn.io domain with proper DomainResolving.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Bearer token auth middleware on POST /register and /records
- Throttle: 10 registrations/min, 20 DNS updates/min
- Token configurable via API_TOKEN env var (disabled when empty)
- Daemon alias validation: a-z 0-9 . - up to 255 chars
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- DaemonRpc: try/catch with stale cache (1h TTL) when daemon is down
- WalletRpc: try/catch with clear error message
- Health endpoint: status=offline/degraded/critical/low_funds/healthy
- Reports wallet_online, daemon_online, stale flags
- Reduced daemon timeout from 10s to 5s, wallet from 30s to 15s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- GET /v1/names/records/{name} reads from LNS sidechain (/resolve)
- POST /v1/names/records/{name} writes via update_alias on chain
- Records encoded in alias comment: dns=TYPE:HOST:VALUE,...
- LNS_URL config for sidechain endpoint
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- POST /v1/names/register endpoint with wallet RPC integration
- WalletRpc service for alias registration via daemon wallet
- Blade views for homepage, explorer, names directory, network status
- Explorer and Names modules with view namespaces and web controllers
- Pool endpoint graceful offline handling
- Explorer block detail, aliases, search views
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
getAliasByName now returns null when daemon responds with status
NOT_FOUND or empty address. /v1/names/available/{name} correctly
reports available=true for unregistered names.
Co-Authored-By: Charon <charon@lethean.io>