Files
web-terminal/relay-auth/src/index.ts
Yaojia Wang e7f3bd05f0 feat(tunnel): zero-touch tunnel enrollment — control-plane PKI, host agent, iOS, nginx isolation
Customers install one command / log in once; hardware-generated keys never leave the
device; CSRs return certs + subdomain; frpc + base-app run as durable services. No .p12,
no manual cert import. Implements the MVP fast-path of docs/PLAN_TUNNEL_AUTOMATION.md.

Control-plane / PKI (control-plane/):
- ca/x509-assembler.ts: single KMS-signed real X.509 issuance primitive (Ed25519 + P-256)
- ca/csr-ec.ts: P-256 PKCS#10 proof-of-possession (verifyCsrPoPEc) + CSR-key routing
- ca/frpclient-issue.ts, ca/device-issue.ts: P-256 frp-client + device leaf signers
- ca/rotate.ts + api/renew.ts: real-X.509 /renew + /device/:id/renew (mTLS current cert)
- registry/devices.ts: device registry + per-account cap/rate-limit
- auth/session.ts: device:enroll capability token mint/verify
- api/device-enroll.ts: POST /device/enroll (ownership-gated, deny-by-default)
- pairing/native-redeem.ts + shared gateAndConsumePairingCode; api/provision.ts native arm
- boot/native-ca.ts + main.ts: wire two P-256 CAs + issuers + routers (dev / KMS fail-fast)

Contracts: relay-contracts enroll right; relay-auth SPIFFE /device/ arm + spiffeIdFor(kind)

Host agent (agent/):
- transport/frpcToml.ts; provision/frpcBinary.ts + untar.ts (verify-download + traversal-safe extract)
- keys P-256 keygen/CSR/loadIdentity; service two-unit install + BIND_HOST loopback S-GATE
- net/loopbackLiteral.ts strict guard; health/probe.ts + transport/frpSupervise.ts; cli pair --install

iOS (ios/Packages/ClientTLS): SecureEnclaveKey + CertificateSigningRequest + DeviceEnrollmentClient
+ Keychain enroll refactor (SecKey/Security.framework end-to-end, avoids the -25300 trap)

Isolation (deploy/nginx): njs/getCertSub.js SAN parser + zone-anchored map -> 403

Verified: 758 tests green (control-plane 246, agent 267, relay-auth 133, relay-contracts 85,
iOS ClientTLS 27), all tsc clean; real nginx+njs docker 403/200/400; Swift CSR accepted by
the real control-plane verifier; frpc extract byte-identical to `tar -xO`. Cross-validation
caught + fixed 5 real defects (1 critical, 4 high). Remaining = infra (KMS, nginx deploy,
VPS frps, physical iPhone) per PROGRESS_LOG runbook.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 16:11:13 +02:00

106 lines
3.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* relay-auth (P5) public barrel — the authorization surface P1/P3/P6 import. Imports
* relay-contracts (§4) read-only; never redefines a frozen contract. Socket-free (no ws/xterm/ANSI
* parser → INV2/INV11 hold by construction).
*/
export * from './types.js'
// Config (INV9)
export {
configureVerifyKey,
loadVerifyKeyFromEnv,
getVerifyKey,
KeyConfigError,
} from './config/keys.js'
// T2 capability tokens + DPoP + device-auth proof
export { issueCapabilityToken, CONNECT_TOKEN_MIN_TTL_SEC, CONNECT_TOKEN_MAX_TTL_SEC } from './capability/issue.js'
export {
verifyCapabilityToken,
verifyDpopProof,
readCnfJkt,
subAccountId,
hasRight,
peekExp,
type DpopContext,
} from './capability/verify.js'
export { CapabilityError } from './capability/errors.js'
export {
signDeviceAuthProof,
verifyDeviceProof,
deviceProofAccount,
type DeviceProofBinding,
} from './capability/device-proof.js'
// T3 authz
export {
authorizeConnect,
authorizeReattach,
type AuthzOutcome,
type ConnectRequest,
type ReattachRequest,
} from './authz/decide.js'
export { accountIdFromToken, principalFromToken, AuthzInputError } from './authz/principal.js'
// T4 audit
export { buildAuditEvent, audit } from './audit/log.js'
export { assertZeroPayload, ZeroPayloadViolation, MAX_METADATA_LEN } from './audit/redact.js'
export { onAuditEvent, type Alerter, type AlertKind } from './audit/alert.js'
// T5T8 human auth
export { startRegistration, finishRegistration } from './human/webauthn/register.js'
export { startAuthentication, finishAuthentication } from './human/webauthn/authenticate.js'
export * from './human/webauthn/verifier.js'
export {
generateTotpSecret,
verifyTotp,
checkTotpAttemptRate,
recordTotpFailure,
} from './human/totp/totp.js'
export {
buildAuthUrl,
exchangeCode,
verifyIdToken,
randomUrlToken,
pkceChallenge,
OidcError,
type OidcConfig,
type OidcTokenSet,
} from './human/oidc/oidc.js'
export {
policyForHost,
needsStepUp,
recordStepUp,
DEFAULT_STEPUP_MAX_AGE_SECONDS,
} from './human/stepup/stepup.js'
// T9 mTLS / SPIFFE
export { spiffeIdFor, parseSpiffeId, trustDomain, SpiffeError } from './agent/spiffe.js'
export type { SpiffeKind } from './agent/spiffe.js'
export {
verifyAgentCert,
defaultParseX509,
type MtlsVerifyResult,
type ParsedCert,
type ParseCert,
} from './agent/verify-mtls.js'
export { shouldRotate, DEFAULT_ROTATION_PLAN, DEFAULT_CERT_TTL_SECONDS, type RotationPlan } from './agent/rotate.js'
// T10 revocation
export { revoke, revokeToken } from './revocation/revoke.js'
export { isTokenRevoked, killsScope } from './revocation/check.js'
// T11 rate-limits
export {
policyForPlan,
PRE_AUTH_POLICY,
checkPreAuthRate,
checkConnectRate,
checkConcurrentSessions,
checkEnrollRate,
} from './ratelimit/quota.js'
// T12 enforcement
export { onUpgrade, type UpgradeContext, type EnforceDeps } from './enforce/onUpgrade.js'
export { onReattach, type ReattachContext } from './enforce/onReattach.js'