Conversation
Add a browser-only Vite entry that reuses the legacy routes with typed Redux fixtures and a single mocked Tauri seam. Cover the reference states with a route index and smoke tests without changing page or native code. Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
Build the Next standalone console during production packaging, preserve its monorepo runtime layout under the Tauri target profile, and launch it with the reference service environment. Record deterministic file hashes and verify the staged redirects and rewrites with focused tests and a live stub smoke. Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
Stage the reference implementation and its workspace dependencies in a deterministic non-flattened Tauri resource root, rebuild the native modules for the shipped Node runtime, and verify loopback health with the same launcher used by the bundle. Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
Add the opt-in tray runtime and authenticated console webview for the unified stack. The runtime attaches to an existing RI and console, stores the owner credential in the OS keychain with a protected fallback, and preserves the legacy Tauri path when the flag is unset. Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
Allow browser-bound runs to acquire a surface from a host agent before readiness checks and release the host-owned surface during cleanup. Preserve the existing lease manager and compatibility path while documenting the host contract and covering admission, readiness, and release behavior. Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
Add a policy-driven supervisor for packaged sidecars with explicit environment, readiness, restart, lifecycle-event, and process-group policies. Keep existing server and ref_server call sites unchanged while the adapter and real-child process tests establish the shared behavior. Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
Keep the legacy harness aligned with the existing connector update control and evaluate the mode-aware Vite config before applying mutation overlays. Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
This was referenced Sep 16, 2026
Stage RI and Console under the same profile-scoped target root so Tauri resources, local production builds, AppImage finalization, and artifact verification agree. Sign nested macOS native files before final app sealing and verify packaged roots on Linux x64 and macOS arm64. Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
Use A2's profile-scoped target root for RI staging and make verification, Tauri resources, release packaging, and source test discovery consume the same layout. Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
Update the production build contract test for the target variable introduced by the release staging lane. Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
Run the unified-stack browser capability provider inside Tauri so the reference implementation can request browser sessions without owning desktop process lifecycle. The host binds an authenticated loopback endpoint, allocates one persistent profile per connector, waits for a DevTools endpoint, and terminates leases on release or Tauri shutdown. The existing browser launch and discovery paths remain shared with the desktop lease implementation. Expose the endpoint and startup token through the host environment helper for supervisor wiring while keeping the supervisor and reference-implementation changes separate. Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
Expose owner connector package lifecycle beside the existing source setup catalog. Keep installation separate from source binding configuration, target only the signed catalog digest selected by the server, and show pending or failed mutations inline so the card remains honest during activation. Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
This was referenced Sep 16, 2026
Connecting a first source registered one owner connector template, and the catalog builder then iterated templates alone, so the add-source page dropped from 45 connectors to 1. Templates now enrich the catalog rather than gate it: every manifest-known connector a template did not already cover is appended. Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
The console displayed PDPP as its owner-facing product name even though the owner decision is DataConnect. Centralize a fixed DataConnect identity in the shared brand package so the shell, metadata, icons, startup surface, and recovery copy stay aligned; retain PDPP as protocol attribution. Add Settings > About with product/build/license/NOTICE/support links and specific TODOs for the privacy URL and complete dependency notices. Remove stale PDPP build arguments and update owner-facing product copy. Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
Brings the data-connectors tools repin (ee11b09dc) and its lockfile, which the integration branch predated. Every workflow on this branch was failing at `npm ci` because package.json and package-lock.json were out of sync. Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
Flatten the source catalog, expose package state, and share connector marks across console identity surfaces. Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
…harness The integration merge kept `legacy.html`, `src/legacy-harness/`, and its route test, but dropped the `legacy:ui` package script, so the one-command path into the legacy UI reference was broken. This restores that script and adds the harness README covering the run command, the fixture routes, and the manual-upload boundary. Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
Add the desktop provider lifecycle seam, HTTPS user-supplied-origin adapter, and keychain-backed credential references. Persist the four reachability fields and restart the managed loopback stack after the settings flow confirms an owner password. Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
Brands the console as DataConnect and adds the About surface. PR #155. Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
Resolves the console page-header conflicts with the DataConnect branding merge: keeps the connector logo markup from this branch and the DataConnect product wording from integration. Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
Redesigns the add-source catalog as a flat list and shows connector logos across the console. PR #158. Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
Restores the legacy:ui script and documents the legacy harness. PR #157. Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
Add the embedded ngrok Rust provider with edge termination and TLS/TCP passthrough profiles, keychain token validation, origin discovery, and remote-access lifecycle tests. Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
Resolves the settings page conflict by keeping both surfaces: the Remote access section from this branch and the About section from the DataConnect branding merge. Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
Add startup parsing and request-boundary enforcement for bind, origin, trusted host, and proxy settings. Tie owner authentication to non-loopback exposure and update desktop/console diagnostics. Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
Adds the desktop remote access provider seam, the user-supplied HTTPS origin provider, and the /settings Remote access surface. PR #159. Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
privacyBadgeForPosture() returned "Provider cannot read your data" for all
three postures, so the switch was decorative. Under Public URL that claim is
false: the owner supplies the proxy, and whether its operator reads plaintext
depends on that proxy's TLS termination, which we cannot inspect.
Each posture now reports its own verifiable property. The criterion: state only
what we can actually verify about who can read plaintext, and never assert a
negative we cannot prove.
off -> "No provider - this device only"
my_devices_only -> "Unavailable - no provider yet"
public_url -> "Depends on your proxy - it can read your data unless it
passes TLS through"
The return type is now a union of those three strings, so the old blanket claim
will not typecheck. The detail panel for a configured origin hardcoded the same
false badge in JSX; it now calls the function and says plainly that DataConnect
cannot verify the proxy's TLS handling.
The setting also rendered its "off" placeholder whenever the config load failed,
which is how the false badge stayed invisible: an unknown state looked like real
state. Loading, missing-bridge, and load-failure are now distinct and explicit,
no posture row is preselected until a real config is read, and the origin panel
stays hidden until then.
Tests assert the honest per-posture wording, keep the never-blank coverage, and
add a regression test that no posture may claim a provider cannot read the
owner's data.
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
Assisted-by: AI
The base branch added dependencies in the same Cargo.toml region as this branch and upgraded several crates (sigstore 0.13 to 0.14, dirs 6 to 7), which conflicted with the ngrok and url entries added here. Both sides of the Cargo.toml conflict are additive, so the resolution keeps all four entries. Cargo.lock was regenerated from the base branch's lockfile rather than hand-merged, so the resulting lock reflects the base branch's upgraded crates plus the ngrok tree; cargo metadata --locked accepts it. Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
…chability contract The reachability contract discards x-forwarded-* headers from untrusted peers. The redirect_uri mismatch test spoofs x-forwarded-host to simulate origin drift, so its header was stripped, the callback recomputed the legitimate redirect_uri, and the request completed 201 instead of the expected 400. The mismatch branch was no longer reachable by that route, leaving the rejection path uncovered. Declare the loopback peer the test client connects from as a trusted proxy, so the spoofed forwarded host survives the request boundary and the mismatch is evaluated as before. The production redirect_uri check is unchanged. Verified the restored test is not vacuous: disabling the mismatch guard in ref-provider-auth.ts makes it fail, and restoring the guard makes it pass. The file goes from 18/19 to 19/19, and tsc --noEmit is clean. Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
fix(console): make the remote-access privacy badge tell the truth
…hability contract The declared-origin reachability contract (#160) changed how the server derives its own public origin per-request: forwarded headers are only honored from peers the deployment declares as trusted proxies, and even then a trusted proxy is not guaranteed to attach identical x-forwarded-* headers to every hop of a flow. The callback route recomputed redirect_uri from the live callback request and rejected the flow whenever that recomputation didn't byte-for-byte match what was recorded at initiate, so a legitimate owner authorizing a connector through a stable, trusted proxy could be refused at callback for no reason tied to any actual origin drift -- only to which headers that particular HTTP request happened to carry. Fix: the code exchange now always uses the redirect_uri persisted at initiate (pending.redirectUri), since that's the value the provider actually authorized against -- not a value recomputed from ambient request state. The recompute-and-compare check stays, but only rejects when the callback request itself presents an explicit, conflicting forwarded-origin claim; a callback that simply omits forwarded-host info carries no evidence of tampering and no longer trips a mismatch. The existing security test (a spoofed x-forwarded-host from a trusted peer must still be rejected before code exchange) continues to pass unmodified. Added coverage for the case that was regressing: a trusted proxy that omits x-forwarded-host on the callback leg while it was present at initiate must still complete normally. Full RI suite: 7 failing (unchanged baseline; unrelated to this route), provider-auth-lifecycle.test.ts 20/20, tsc --noEmit clean. Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
…existing RI failures Cluster A (4 tests, provider-auth adapter registration): resolveProviderAuthAdapter loaded @pdpp/polyfill-connectors/provider-auth-adapters via require() while test/ connector code registers adapters through a plain ESM import of the same package. Under tsx, require() and import() of this ESM package do not share a module instance, so each side held its own adapter registry Map and registrations made via import were invisible to require()-side resolution. Switch the resolver to the same import() loading path external registrants use. Cluster B (2 tests, connector-knowledge boundary): the zero-connector-knowledge data-load scanner's line-pinned allowlist entries for connector-install/index.ts and polyfill-manifest-reconcile.ts had drifted stale after later merges (docker-connectors-from-catalog, developer-connector-sources, both 2026-09-16) inserted lines above the reviewed call sites, and local-source.ts's two structurally-identical generic manifest/state reads were never reviewed at all. Re-derived the two stale line pins and added the two new entries after direct inspection confirmed all four sites read RI-owned generic filenames joined with operator/developer-supplied roots, never connector-specific literals -- not a stale detector papering over a real violation, and not a real violation either. Cluster C (1 test, malformed options_schema): the local ConnectorOptionsSchemaError class declared in polyfill-connectors-runtime.ts was never the class actually thrown by the package's real resolver, nor the one test code imports directly from the package -- same require()/import() module-instance split as Cluster A, but on a class identity rather than a registry. instanceof against either side's copy would miss errors from the other. Drop the local class and classify by constructor.name, which is stable across both instantiations, instead of object identity. RI suite: 7 failing -> 0 failing (10499 passing), typecheck clean. Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
apps/console/src/proxy.ts (Next 16 edge middleware) imported OWNER_AUTH_COOKIE_NAME from pdpp-reference-implementation/owner-session, which pulls in `import crypto from "node:crypto"` at owner-session.ts:4. node:crypto does not exist on the edge runtime, so webpack raised UnhandledSchemeError: Reading from "node:crypto" and the console build failed, blocking CI review of #160/#163/#164. The break is latent, not caused by #164: #164's dynamic import chain (provider-auth-adapters -> oauth2-generic-provider-auth -> provider-auth-adapter) contains no node:crypto import. proxy.ts uses owner-session for exactly one thing: the OWNER_AUTH_COOKIE_NAME string constant. That constant and its sibling TTL/subject constants are plain literals with no dependency on crypto. Extracted them into a new owner-session-constants.ts, added a matching package export, and had owner-session.ts re-export them so every existing consumer (owner-token.ts, owner-auth.ts, and RI tests) keeps resolving the same names unchanged. proxy.ts now imports the constant from the new crypto-free module. No security behavior changed: session minting, verification, HMAC, and TTL semantics are untouched, and the cookie name constant is still "pdpp_owner_session". Validated: - npm run --workspace pdpp-console build succeeds (Next 16.3.4, webpack, no UnhandledSchemeError). - reference-implementation owner-session/owner-auth tests: 27/27 pass (test/owner-session.test.ts, test/owner-session-env.test.ts, test/owner-auth.test.ts, test/owner-auth-fail-closed.test.ts). - apps/console test suite: 2127/2205 pass; the 78 failures are pre-existing and unrelated (connector catalog/UI/palette tests, reproduced identically with this change reverted); no proxy/owner-session/owner-auth/owner-token test regresses. - grep -rn "node:crypto" reference-implementation/server confirms the new owner-session-constants.ts module has none, and proxy.ts's import chain no longer reaches a crypto import. - Cookie name constant confirmed unchanged: "pdpp_owner_session". Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
fix(console): keep node:crypto out of the edge proxy bundle
feat(reference): enforce a declared-origin reachability contract
feat(desktop): add an ngrok remote access provider
Add the embedded ngrok Rust provider with edge termination and TLS/TCP passthrough profiles, keychain token validation, origin discovery, and remote-access lifecycle tests. Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
Rebase onto integration/unified-stack, which merged the honest-badge fix (PR #162) after this branch was cut. That fix replaced the uniform, false "Provider cannot read your data" badge with three honest, per-posture strings, because a proxy we do not operate cannot be asserted safe. This commit keeps that fix and layers ngrok on top without reintroducing the false uniform badge. `privacyBadgeForPosture` still returns the three honest posture-level strings; a new, separate `ProviderPrivacyBadge` covers the two ngrok endpoint shapes, since the answer for Public URL now depends on which provider and mode the owner picks: - ngrok HTTPS edge termination: "Provider can read your data" (ngrok holds the certificate and reads plaintext at its edge). - ngrok TLS passthrough: "Provider cannot read your data", proven for ngrok Rust SDK 0.19.0 specifically (session.rs sets passthrough_tls = opts.tls_termination.is_none(); the adapter never calls termination(), so the edge relays ciphertext without decrypting it). An SDK upgrade must re-verify this claim. The ngrok authtoken is a one-time paste stored in the OS keychain, never re-requested. A reserved domain is optional and requires a paid ngrok plan; leaving it blank accepts ngrok's assigned hostname. Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
The user-supplied-proxy Public URL option claimed "Provider cannot read your data". DataConnect does not operate that proxy and cannot see where it terminates TLS, so the claim is unprovable — the same false claim PR #162 removed, reappearing in the new per-provider option list. Replace it with a conditional badge that states the real dependency on the operator's own TLS termination, add the value to the ProviderPrivacyBadge union, and widen the test assertion that enumerated the two old badge strings so it accepts the new honest value without weakening the check. Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
feat(console): offer ngrok as a Public URL provider
fix(reference-implementation): close 3 real defects behind the 7 pre-existing RI failures
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This draft integrates seventeen unified-stack lanes into one opt-in desktop path. With DATACONNECT_UNIFIED_STACK=1, DataConnect starts or attaches to the reference sidecars, injects the owner session into the console webview, and retains the existing legacy path when the flag is absent.
The lane implementations are #135 for the legacy render harness, #136 for the tray/webview bootstrap, #137 for the staged operator console, #138 for host-provided browser surfaces, #139 for the staged reference runtime, #140 for typed sidecar supervision, #142 for release staging and packaged-stack verification, #143 for host-owned browser leases, #144 for the console connector-install panel, #145 for signed RI OCI connector installation, update, and activation, #146 for tray-launched profile-scoped sidecars and bounded supervision, #148 for bounded non-blocking unified shutdown, #149 for packaged connector manifests in the staged console, #150 for the runtime console browser route, #152 for catalog-backed Docker connector installation, #153 for URI-keyed owner catalog joining and development connector visibility, and #154 for developer-local connector sources.
The integration preserves both staged resource trees, now profile-scoped under
target/<profile>/reference-stack/{ri,console}, resolves the Tauri dependency union, keeps A3's explicit process-target validation, and supports B's attach-mode RI and console URLs. The release workflow stages, verifies, packages, and checks both roots. Integration-only repairs reconcile the legacy harness, mode-aware Vite mutation overlays, and generated-target test discovery.Verified locally: root typecheck; root Vitest (111 files, 1,006 tests); reference-implementation and console typechecks; connector-protocol, collector-runtime, and mcp-server builds; RI install (19 tests), connector resolution (5), owner templates (15), and admission routes (10); RI staging and reference-stack smoke; console staging and smoke; focused Rust tests for process_supervisor (9 passed, 1 ignored), unified (8), owner_credential (2), ref_server (5), and the host browser surface (5); the four RI browser-surface test groups (129 tests); and a resource-free Rust cargo build. The new lane-specific checks also cover the packaged-manifest resolver (1/1), URI-keyed catalog joining and development visibility (3/3), developer-local source behavior (6 RI/console tests and 2 Rust tests), and the catalog-backed Docker install path.
Not verified: the full Tauri resource bundle, macOS signing, a live owner desktop run, and cross-platform targets. The normal cargo build reaches Tauri resource validation but finds a dangling staged
.bin/patchrightlink; the resource-free build passes. Lane CI fetch failures for legacy Sigstore/GHCR assets and the no-mutants mutation result are infrastructure outcomes, not code failures reproduced by this local verification.Assisted-by: AI