feat(ios): P1-A — server touch-points (lastOutputAt, APNs sender+token endpoint) + APIClient P1 contract

T-iOS-37: LiveSessionInfo.lastOutputAt additive-optional field + manager.list() mapping (+4 tests; web consumers unaffected)
T-iOS-20: src/push/apns.ts — env-gated (all-or-disabled, no crash, zero key-material logging), hand-rolled ES256 JWT
(node:crypto ieee-p1363, zero new deps), NEEDS-INPUT/DONE payloads with structural minimization, token store per
subscription-store conventions, combineNotifyServices parallel to web-push, POST/DELETE /push/apns-token per frozen
wire shape (G-guard, 5/min/IP, 8kb); 65 tests incl. dual-channel e2e vs local fake APNs
T-iOS-38: APIClient builders — apns-token (client-side hex mirror, pre-network reject), projects/detail (lossy decode,
single-point percent-encoding), prefs (unknown-key byte-exact round-trip preservation), public four-tier HostNetworkTier
Coordination: webterminal:// CFBundleURLTypes pre-registered in project.yml for T-iOS-22
Verified: root 1470 tests + tsc clean; APIClient 76 tests, 95.26% coverage; wire-shape cross-check zero mismatches
This commit is contained in:
Yaojia Wang
2026-07-05 13:34:01 +02:00
parent aa956fcbb4
commit 4871e8ac3d
20 changed files with 3319 additions and 48 deletions

View File

@@ -253,6 +253,12 @@ export interface LiveSessionInfo {
cols: number; // current PTY size (for the manage page)
rows: number;
telemetry?: StatusTelemetry | null; // B2: latest telemetry for the thumbnail wall
/** T-iOS-37: last pty.onData timestamp (epoch ms; = createdAt until first
* output — createSession inits it to spawn time). Serialized from the M3
* runtime record so clients can derive an unread watermark
* (lastOutputAt > local last-seen). Additive OPTIONAL: older consumers
* that build or read LiveSessionInfo without it stay valid. */
readonly lastOutputAt?: number;
}
/* ───────────────── project manager (v0.6, §4.3 FEATURE doc) ──────────────── */