Product schema on name pages with brand, offers, URL. BreadcrumbList
on pricing page. Triggers Google rich results and schema.org monitoring
alerts for brand sunrise names. Rate limit headers already provided
by api middleware group (X-RateLimit-Limit/Remaining).
Commit #103.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>
SitemapController generates XML sitemap with all static pages + all
registered name pages from chain. Cached 1 hour. 140+ name pages
make each registered brand discoverable by search engines.
Commit #101.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Multi-tenant scoping via CorePHP tenant package. workspace_id column
added to all three tables. Existing records backfilled to workspace 1
(Lethean CIC). workspaceContextRequired=false allows public API calls
without workspace context.
Commit #100.
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>
Symlinked core-api, php-commerce, php-tenant into app/Core/.
All migrations ran (50 tables). Tenant feature seeder ran.
Workspace 'Lethean CIC' created with admin user Charon and
'Lethean Registrar' namespace. SetupWorkspace artisan command
for repeatable provisioning.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ClaimApproved mailable sent when admin approves a claim — dark
themed HTML email with name, next steps, and CTA links. Wrapped
in try/catch so email failure doesn't block approval.
Dynamic SVG OpenGraph images at /names/{name}/og.svg — shows name,
type badge (Registered/Reserved/Gateway/Available), and branding.
og:image meta tag added to name detail pages via @push('head').
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
tests/TestCase.php bootstraps app via Core\Boot::app() with kernel
bootstrap. DatabaseTransactions for test isolation. PHPUnit config
with array cache/session. 12 tests written, unit tests pass.
HTTP endpoint tests need chain daemon mock to run standalone.
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>
POST /v1/names/claims/{id}/approve — changes status, logs activity.
POST /v1/names/claims/{id}/reject — changes status, logs activity.
Both require auth.api middleware. Validates claim exists and is pending.
Completes the claim lifecycle: submit → review → approve/reject.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
DNS change tickets now persisted in MariaDB via DnsTicket model.
Survives cache clears and container rebuilds. Model has open(),
confirm(), fail() methods and pending/queued scopes. Controller
updateRecords and ticket endpoints refactored. RetryDnsTickets
command queries model instead of cache.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
13 tests covering CheckAvailability, SubmitClaim, NameClaim model
scopes, NameActivity logging, and HTTP endpoints. PHPUnit config
added. Tests need TestCase base class setup to run — framework
testing infrastructure TBD.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
NameResource transforms alias data with parsed type, capabilities,
and owner_type (registry/community). ClaimResource formats claim
responses. Lookup endpoint uses NameResource, claim uses ClaimResource
with additional message. Follows CorePHP patterns/building-rest-apis.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
NameActivity model with log() static method. Stores event, name,
properties (JSON), and hashed IP (GDPR). SubmitClaim action now
logs 'claimed' event. Ready for dns_updated, registered, etc.
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>
RetryDnsTickets command now scheduled everyMinute with
withoutOverlapping. Runs via supervisor scheduler in the container.
Queued DNS changes retry automatically without manual intervention.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Database now uses native MariaDB (lthn_io database). Container
connects via host.docker.internal:3306. Claims persisted in proper
RDBMS that survives container rebuilds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Container was using host path for SQLite. Now creates database.sqlite
during Docker build and sets DB_DATABASE=/app/database/database.sqlite
in compose env. Migrations run on startup via laravel-entrypoint.sh.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
WalletRpc::getBalance() can throw when wallet is on localhost and
app runs in Docker. Wrapped in try/catch so status page degrades
gracefully instead of 500ing.
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 Actions pattern — single-purpose classes with static ::run().
Controller methods now delegate to Actions. Each Action validates,
executes, and returns typed results. Enables reuse from commands,
jobs, and tests without going through HTTP.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Claims stored in Cache were lost on cache clear. Now persisted in
name_claims SQLite table via NameClaim Eloquent model. Auto-generates
claim_id via random_bytes. Scopes: pending(), approved(). Methods:
approve(), reject(). Status page updated to query model.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The @cspnonce Blade directive isn't available (Headers module not
loading). Reverted to plain <script>/<style> tags. unsafe-inline
in CSP config handles security. Nonces re-added when Headers Boot
is properly integrated.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Container on noc-net network for Traefik DNS resolution.
Traefik routes to http://lthn-io:80. All pages serving 200.
Disabled Mod/Home (conflicting / route), disabled subdomain
Website modules (Octane can't scope routes by domain at boot).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Explorer, Docs, Pool, Trade, Names subdomain Website modules had
routes at root (/) that conflicted with the Lethean homepage when
registered unconditionally (required for Octane). Disabled subdomain
routes — Mod modules handle prefixed paths (/explorer, /names etc).
Container now serves all 10+ pages correctly on FrankenPHP Octane.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Octane registers routes once at startup when $_SERVER['HTTP_HOST']
is not available. All Website modules now register routes without
domain checks. Pool/Trade/Names subdomain routes disabled (views
not built). Home module disabled (Lethean handles homepage).
Container now serves 200 on FrankenPHP Octane.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Dockerfile from hostuk (FrankenPHP 1-php8.5), stripped scorer binary.
Supervisor config simplified for lthn.io (no horizon/reverb).
Octane + Predis installed. docker-compose.yml with Traefik labels,
host.docker.internal for daemon/wallet/LNS access, file cache.
TODO: Fix view namespace resolution inside container (localhost
doesn't match Lethean $domains). Need to add localhost to Lethean
$domains or test with proper Host header.
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>
Added @cspnonce to all inline <script> and <style> tags in layout,
explorer, and register views. Enabled nonce generation in headers
config. unsafe-inline kept as fallback. Nonces will activate after
container restart when the Headers Boot registers the Blade directive.
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>
Full documentation site with sidebar navigation, search, markdown
rendering, and prev/next navigation. Initial content: introduction,
chain overview, name system, API reference, CIC governance.
Lethean Boot.php now only registers routes on matching domains
(lthn.io, testnet.lthn.io, localhost) — no longer bleeds onto
api.*, docs.*, explorer.* subdomains.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All three Website modules now use $event->routes() with domain-scoped
routing. On their subdomain (e.g. pool.lthn.io): routes serve at root.
On lthn.io: the Mod modules handle the prefixed paths (/pool, /trade,
/names). Removed loadViewsFrom from boot() where views are already
registered by the corresponding Mod modules.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
On explorer.lthn.io: routes serve at root (/). On lthn.io: Mod/Explorer
handles the /explorer prefix. Adopted CorePHP $event->routes() pattern.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Lethean module now checks HTTP_HOST and skips route registration on
api.* domains. This lets the Website/Api module's homepage route win
on api.lthn.io. Also migrated to $event->routes() pattern.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Widget.js default API URL changed to api.lthn.io. API docs page "Try"
links now use configurable API_URL. Base URL display is dynamic.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds paid fast-track option to sunrise page, reserved name detail
pages, and pricing table. Links to Blesta order form for BTCPay
payment. Three clear paths: free DNS verification, free manual
verification, or $49 BTC fast track with immediate registration.
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>
POST endpoints on /v1/* were returning 419 CSRF mismatch because
$event->routes() wraps routes in the web middleware group which
includes ValidateCsrfToken. External clients (Blesta, curl) can't
send CSRF tokens. withoutMiddleware() on /v1/* prefixes fixes this.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The $event->routes() pattern applies SecurityHeaders middleware which
sets CSP. Inline <style> and <script> tags in Blade views need
unsafe-inline to render. Published config from framework with fix.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The Why Lethean page (/about) existed but was unreachable from the nav.
CTOs need to find the CIC governance and positioning page.
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>
Name detail pages now show DNS records from sidechain, ITNS sidechain
registration, services links (DNS/SSL/Proxy), and CIC governance label
for community members. Available names link to claim page.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
API reference now covers all 29 endpoints across Names (13), Proxy (5),
Gateway (4), and Explorer (7). All GET endpoints verified returning 200.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Shows blockchain daemon, wallet, gateways, name registry, and consensus
status with green/amber indicators. Chain stats, hardfork status, and
gateway details. Footer link added.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds claim/listClaims endpoints so visitors can reserve .lthn names
before chain registration is fully automated. Claims are stored with
email for notification when approved. Admin endpoint lists all claims.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>