/** * NetworkProvider interface — the documented contract for DashCaddy * Private Network providers (DC-140, specs/PRIVATE-NETWORK-SPEC.md §3). * * Everything above the provider (people, groups, resources, access map, * forward_auth, Technitium names, the CA, the UI) is shared and talks to * the network ONLY through this contract — never to a provider module * directly. Resolution goes through src/network/registry.js. * * ## Capability flags * * `capabilities()` returns: * - invites provider can mint invite URLs itself (TS user-invites / * WG one-time token). When false, DashCaddy mints its own. * - splitDnsApi provider exposes a split-DNS API (Tailscale does; * WireGuard writes Technitium directly instead). * - perPeerFirewall provider enforces per-peer rules natively (WG nftables; * Tailscale relies on ACLs, so false). * - selfHosted no outside control-plane dependency (WG true, TS false). * * Feature modules MUST check capabilities and degrade cleanly. * * ## Methods (all async, all return plain JSON, all validated) * * id() → 'tailscale' | 'wireguard' * capabilities() → { invites, splitDnsApi, perPeerFirewall, selfHosted } * getStatus() → provider health/summary (TS: local `tailscale status`; * WG: `wg show dump` + iface state) * listDevices() → device list merged with local online state * listPeople() → provider users projected to * { id, displayName, email, createdAt } * createInvite({ role, email? }) → { inviteUrl, id } — email is OPTIONAL; * when omitted, the provider returns a link without sending * (link-first, DC-085 pattern; never log inviteUrl raw) * revokeInvite(id) → { revoked: true } * blockPerson(userId) → reversible network-level block (TS: expire every * device key owned by the user; WG: drop peer + deny set) * unblockPerson(userId) → reverse of blockPerson (TS: no-op at provider * level, DashCaddy re-grants via syncAccess) * removePerson(userId) → delete provider devices + revoke invites * revokeDevice(deviceId) → expire/remove a single device's access * syncAccess(accessMap, resources) → compile + dry-run + push provider * rules (hash-guarded). Injected per provider in later DCs * (TS ACL compiler = DC-148; WG nftables = DC-150). * whois(ip) → which person owns the connecting device * configureDns({ zone, server }) → split-DNS setup when splitDnsApi * * ## Error contract * * All failures throw ProviderError (src/network/errors.js) with a `code` * and `retryable` hint. Providers map their native errors at the boundary * so no provider-specific error type ever escapes this package. */ 'use strict'; module.exports = { /** Method names every provider must implement (documented contract). */ CONTRACT_METHODS: [ 'id', 'capabilities', 'getStatus', 'listDevices', 'listPeople', 'createInvite', 'revokeInvite', 'blockPerson', 'unblockPerson', 'removePerson', 'revokeDevice', 'syncAccess', 'whois', 'configureDns', ], };