Skip to content

feat(core): add provider-scoped pi observer config and auth - #3

Closed
ZeR020 wants to merge 2 commits into
stack/3-viewer-routesfrom
stack/4-pi-observer-auth
Closed

feat(core): add provider-scoped pi observer config and auth#3
ZeR020 wants to merge 2 commits into
stack/3-viewer-routesfrom
stack/4-pi-observer-auth

Conversation

@ZeR020

@ZeR020 ZeR020 commented Aug 17, 2026

Copy link
Copy Markdown
Owner

Fourth stacked PR for pi support (kunickiaj#1430). Depends on layer 3 (stack/3-viewer-routes, #2), layer 2 (#1), and layer 1 (kunickiaj#1473).

Opened on the fork because GitHub cannot use kunickiaj:stack/3-viewer-routes as a base.

Why

Maintainer blocker: a pi API key was offered to every observer provider. An explicit Anthropic/OpenAI observer must not receive an unrelated custom-provider key.

What

  • resolvePiObserverConfig derives provider/model/wire from pi API-key config (cheap-first). OAuth-only installs report unconfigured (oauth-only).
  • Observer auth cascade: explicit → env → oauth → pi → file → command.
  • resolvePiApiKeyForObserver returns a key only when the pi provider matches the effective observer provider (case-insensitive). Never assigned onto persisted observerApiKey.
  • Status/config paths do not echo pi secrets.

Docs stay on layer 8.

Test plan

  • vitest run packages/core/src/observer-client.test.ts packages/core/src/observer-auth.test.ts packages/core/src/pi-observer-config.test.ts — 136/136

Stacked on: #2 / #1 / kunickiaj#1473
Related: kunickiaj#1430, kunickiaj#1429

Copilot AI lite review requested due to automatic review settings August 17, 2026 14:25

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

ZeR020 and others added 2 commits September 12, 2026 12:07
…unickiaj#1678)

* feat(viewer-server): add /api/pi-hooks alias and memory tool routes

Pi events enter the 0.41 ingest seam through a dedicated compat route
that forces source "pi". Memory-tool POSTs reuse the bounded JSON
parser and the shared remember-kind catalog.

* fix(viewer-server): reject untyped memory-tool POST filters

POST expand/explain/distill copied raw filter values into store queries.
Objects such as include_scope_ids:{x:1} were coerced to "[object Object]".
Validate scalar or scalar-array types and return 400 before SQLite.

* style(viewer-server): biome-format memory-tool filter types

* fix(viewer-server): await pi-hooks ingest before reporting counts

* fix(viewer-server): widen remember kinds set for string filter checks

* test(viewer-server): expect hashed pi event ids from main

* chore: retrigger CI after flaky tsc build race

* fix(build): drop tsc --force so parallel declaration emits don't collide

tsc --build --force on core/embeddings/mcp-server/viewer-server re-emits
packages/embeddings/dist/*.d.ts from every parallel pnpm lane. A sibling
lane then reads the file mid-write (TS2306 "is not a module") — the
TypeScript Test build step on kunickiaj#1678. Clean already deletes dist and
tsbuildinfo, which is why --force was added in kunickiaj#650.

* fix(build): clear stale tsbuildinfo so declarations always re-emit

Address review P1 on kunickiaj#1678: without --force, a second build exits 0 but
tsc --build trusts the surviving tsconfig.tsbuildinfo after vite empties
dist, so published types entrypoints vanish. Clear the package's own
build info before declaration emission (keeps parallel lanes from
re-emitting referenced packages, the TS2306 race) and assert every
published types file exists after the build.

* fix(viewer-server): guard pi-hooks target and strip routing fields

Address review P1 on kunickiaj#1678: /api/pi-hooks accepted events bound for
another viewer DB and let db_path/identity_target fall into
meta.pi_fields. Resolve the store, validate with
{ requirePairedTargets: true } like the sibling ingest routes, and build
the envelope from untargetedPayload(payload). Adds the pi-hooks case to
the targeted-ingest mismatch suites plus a field-stripping test.

* feat(core): share the memory filter catalog across MCP and viewer

Address review P2 on kunickiaj#1678: the viewer's filter allowlist and
SCHEMA_FILTER_NAMES were hand-copied from the MCP zod schema, so a new
MCP filter could be silently omitted and exclusion filters would fail
open. Move the filter key/type catalog into @codemem/core
(memory-filter-schema.ts), validate viewer request filters against it
per field (rejecting e.g. include_scope_ids: false or
widen_shared_min_personal_results: "abc" with 400 instead of coercing),
and pin the MCP zod shape to the catalog with an exact parity test.

---------

Co-authored-by: Adam Kunicki <kunickiaj@gmail.com>
Derive observer provider/model from pi API-key config without copying
secrets onto observerApiKey. Offer the in-memory pi key only when the
pi provider matches the effective observer provider (D4).
@ZeR020
ZeR020 force-pushed the stack/4-pi-observer-auth branch from 5e4646c to 53d129a Compare September 12, 2026 20:06
@ZeR020

ZeR020 commented Sep 12, 2026

Copy link
Copy Markdown
Owner Author

Promoted to kunickiaj#1693 now that layer 3 is on main.

@ZeR020 ZeR020 closed this Sep 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants