7 Commits
Author SHA1 Message Date
Juan DenisandClaude Opus 4.8 60a676025a Fix wildcard HTTPS reading encrypted DNS creds raw + add encryption tests
Auditing the encryption-at-rest work surfaced one missed read site: sites_https_service
passed the DNS provider api_key/api_secret straight to the cert issuer, but those are
now Fernet-encrypted at rest — so DNS-01 wildcard issuance would have received ciphertext
and failed.

- Add DNSProviderService.decrypted_credentials() as the public, canonical way to read a
  DNS provider's usable creds (nothing reads .api_key raw anymore); use it in
  sites_https_service.
- Add tests/test_provider_secret_encryption.py — 8 proving tests: ciphertext-at-rest +
  plaintext-on-read for DNS / cloud / storage / registrar, the idempotent legacy-plaintext
  migration, and the wildcard path now receiving decrypted creds (the regression above).

pytest: 17/17 pass (8 new + 9 existing test_sites_https.py). Full suite: 187 passed; the
lone failure (test_agent_poll_e2e command roundtrip) is a pre-existing flake — the agent
registry in-memory singleton leaks across tests in that file (passes solo), unrelated here.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 19:55:57 -04:00
Juan DenisandClaude Opus 4.8 fd2313077f Polish connections: domain-expiry alerts, S3 image preview, encryption-health banner
- Domain-expiry notifications: a daily scheduler (RegistrarService.notify_expiring)
  fires through the notification channels when a registrar domain crosses 30/14/7/1
  days or expires, de-duped via a small state file so each crossing alerts once.
- S3 image preview: ImageThumb is now S3-aware (loads objects via short-lived
  presigned URLs); threaded through FileCard / PreviewDrawer / FileManager.
- Encryption-health banner: the Connections hub consumes GET /api/v1/connections
  and warns if any credential is not encrypted at rest (hidden in the happy path)
  — the registry's first real consumer.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 19:43:00 -04:00
Juan DenisandClaude Opus 4.8 bbe6bee267 Unify credential encryption + add a read-only connection registry (#18)
- Encrypt the last plaintext credential store: CloudProvider.api_key_encrypted is
  now Fernet-encrypted on write and decrypted in _auth_headers, with an idempotent
  encrypt_legacy_secrets() migration run at startup. All five stores (source, DNS,
  cloud, registrar, storage) now encrypt identically via app.utils.crypto.
- Add ConnectionRegistry + GET /api/v1/connections: one normalized, secret-free
  list of every connected external account (the "what's connected" source of
  truth). Frontend api.getAllConnections().
- The full write-side "one model replaces five" migration is deliberately not done
  — it would risk five working subsystems for no user-facing benefit. The uniform
  encryption + read registry deliver #18's practical value.

Verified by booting create_app('testing') and running the registry live (returns
a list; /api/v1/connections present in the URL map).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 10:47:59 -04:00
Juan DenisandClaude Opus 4.8 d157fc514d Encrypt provider secrets at rest + add Namecheap registrar (#16, #17)
Encryption-at-rest (#16/#17) for the two provider stores still in plaintext:
- crypto.py: add decrypt_secret_safe (decrypt with plaintext fallback) + is_encrypted.
- DNS providers: encrypt api_key/api_secret on write; decrypt at point-of-use via
  _api_key/_api_secret in the Cloudflare/Route53/DigitalOcean/GoDaddy builders.
- Storage: encrypt secrets in save_config; decrypt in get_config.
- Idempotent encrypt_legacy_secrets() migrations run on startup, encrypting any
  pre-existing plaintext in place. Legacy values keep working via the decrypt
  fallback, so there is no flag day.

Namecheap registrar:
- RegistrarConnection.config_json column for non-secret extras (username, client_ip).
- RegistrarService: Namecheap XML domains.getList (portfolio + expiry), test, and
  MM/DD/YYYY -> ISO date parsing.
- Frontend: namecheap tile is live; the registrar form is provider-aware (GoDaddy
  key+secret vs Namecheap key + username + whitelisted IP).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 10:33:09 -04:00
Juan DenisandClaude Opus 4.8 845df9959e Add S3 bucket browsing to the Files app (#14, #15)
- backend: StorageProviderService.s3_* (browse/read/write/upload/delete/
  presigned-get) + /api/v1/files/s3/* routes, reusing the configured backup
  bucket — no new credentials.
- frontend: an "S3 bucket" target in the File Manager. UI paths stay slash-rooted
  and map to S3 keys server-side, so breadcrumbs/history work unchanged; virtual
  folders from prefixes; presigned-URL download. Folders/rename/permissions are
  disabled and the local-only sidebar is hidden on S3. TargetPicker gained a
  backward-compatible extraOptions prop.
- docs: mark #14/#15 done (Phase 4).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 10:21:39 -04:00
Juan DenisandClaude Opus 4.8 7b6086934d Finalize Connections hub: complete #8 SMTP relay docs + lint cleanup
Follow-up to the connections work already committed in 2e1bdbc + c1d4653
(swept in by a concurrent commit). Commits the two remaining edits:

- docs/CONNECTIONS_ROADMAP.md: mark #8 (SMTP relay) done — a real Postfix
  smarthost (relayhost + SASL) with an OS-agnostic smtplib connection test.
- ConnectProviderModal: drop the unused `provider` arg from EmailBody (lint).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 09:23:06 -04:00
Juan Denis c1d4653f6c Add registrars, GitLab, DO/Godaddy DNS and SMTP relay
Introduce a broad Connections expansion: add RegistrarConnection model, RegistrarService and /api/v1/registrars endpoints to surface domain portfolios and expiry. Add EmailRelayService and API routes plus Postfix relay wiring to configure/test/disable outbound SMTP. Extend DNSProviderService with DigitalOcean and GoDaddy implementations and helpers. Add GitLab support to source connection service and routes. Frontend: expand Connections hub, provider catalog, modal bodies, provider icons, RegistrarPortfolio component, API client methods and styles. Add docs/CONNECTIONS_ROADMAP.md describing roadmap and intent.
2026-06-15 09:19:56 -04:00