summaryrefslogtreecommitdiff
path: root/LocalAPIService.swift
Commit message (Collapse)AuthorAgeFilesLines
* feat: stabilize and document the Local API v1 response contract (v5 step 3)Christian Cleberg10 days1-28/+19
| | | | | | | | | | | | | | | | | | | | | | | | | | | Second v5.0.0 roadmap item: make the Local API's public JSON contract explicit, documented, and regression-locked, so external consumers (Shortcuts, scripts, integrations) have a stable surface with a defined compatibility promise. - LocalAPIContract: new single source of truth for the wire-format version ("v1") and the canonical JSON encoder (ISO-8601 dates, sorted keys). Both the success and error paths in LocalAPIService now route through it, so the format can't drift between them, and the ad-hoc per-call-site encoders are gone. - The response envelope and every payload struct are promoted from `private` to internal so the contract is a first-class, testable part of the module. The transport/handler internals (request parser, HTTP response, secret store) stay private. - Docs/local-api.md documents the base URL/auth, the envelope, the encoding conventions (notably: absent optionals are omitted, not null), every endpoint and its payload fields, the error codes, and the semantic-version-style compatibility policy (additive changes keep v1; renames/removals/type changes bump the version). Linked from the README. - LocalAPIContractTests: 16 structure/"golden" tests pinning the envelope shape, each payload's field names, the enum encodings, and the ISO-8601 date format. They assert structure, not values, so ordinary behavior changes don't churn them but a renamed or dropped field fails CI. Full unit suite: 52 passing.
* feat: add Copy cURL Command button to the Local API page (#30)Christian Cleberg11 days1-0/+5
| | | | | | | | | | | | Adds a one-tap way to get a working, authenticated request from the Local API settings page. copyCurlCommand() copies a curl invocation using the current bound address and token via the Authorization header: curl -H "Authorization: Bearer <token>" http://127.0.0.1:<port>/portfolio Keeps the token in a header rather than a query string, so it stays out of URLs, browser history, and the request-log view (which masks the token). Guards on an empty token, matching copyToken().
* fix: surface the real NWListener error and drop conflicting ↵Christian Cleberg11 days1-5/+4
| | | | | | | | | | | | | | | | | | requiredLocalEndpoint (#30) The Local API failed to start with a generic "Could not start Local API on port 47821" and no actionable cause. Two problems: 1. The NWListener construction catch discarded the caught error and substituted a generic string, so the real NWError was never surfaced or logged. Now the underlying error is logged via stateLogger (matching the .failed branch) and appended to the thrown message. 2. parameters.requiredLocalEndpoint pinned 127.0.0.1:<port> while the same port was passed as the listener's on: argument. Pinning a required local endpoint conflicts with the listener's own port assignment; acceptLocalOnly already constrains binding to the local link. Dropped requiredLocalEndpoint, keeping acceptLocalOnly + allowLocalEndpointReuse.
* fix: StoreKit config path and Swift 6 concurrency warningsChristian Cleberg2026-07-201-6/+8
| | | | | | | | | | | | | | | | | | The StoreKitConfigurationFileReference added in #11 used one '../' too many, resolving outside the repository. Xcode resolves it relative to the .xcodeproj's xcshareddata directory, so two levels reaches the repo root. SweepActivityAttributes is now explicitly nonisolated. The app target sets SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor while the widget target does not, so a type shared by both inferred a main-actor-isolated ActivityAttributes conformance that ActivityKit cannot use from its concurrent contexts. LocalAPIService's logger closures captured self strongly while their inner Tasks declared [weak self]. The weak capture is now on the outer closure and bound before the Task, so the concurrently-executing closure references an immutable strong local rather than the weak capture.
* DomainDig v4.2.0: Add a local-only HTTP API layer for DomainDigChristian Cleberg2026-04-261-0/+1029
Expose DomainDig as a programmable local domain intelligence engine over localhost with explicit user opt-in and token-based authentication. Highlights: - add a localhost-only API server with safe start/stop lifecycle - require a local token for every request and store it in Keychain - add read endpoints for portfolio, domains, history, events, and monitoring - add inspection endpoints that reuse the existing inspection engine - add monitoring enable/disable control endpoints - add structured JSON response envelopes with API versioning - add lightweight capped request logging with clear/reset support - add a Settings UI for Local API enablement, token management, status, and logs - start the server on launch only when enabled - include Local API secrets in local data reset cleanup This is the first programmability release for DomainDig and establishes the foundation for Shortcuts, scripts, and other local automation workflows.