Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 102 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# Agent guidance for integration-proxy

## This repository is platform-agnostic

`integration-proxy` is generic OAuth/catalog plumbing. It knows how to load a
catalog, compose an OpenAPI document from a pinned OAD plus pinned
[Overlay Specification](https://spec.openapis.org/overlay/latest.html)
documents, run the OAuth code/PKCE flows the composed document describes, and
allowlist proxy requests against it. Its *runtime behavior* must never depend
on the name, shape, or business rules of any specific third-party API.

**No platform-specific behavior, branching, or hand-authored data belongs in
this repository's production code.** That includes:

- Hard-coding a platform name (`"moneybird"`, `"google-calendar"`, ...) to
drive a code path in `src/`, outside of already-generic config plumbing
(e.g. deriving an env var name from whatever name the catalog happens to
contain).
- Hand-writing response schema fixes, missing fields, CRUD/collection
structure, pagination quirks, or throttling metadata for a specific API
inline in this repo. These are OpenAPI/Overlay documents, and they are
authored, published, and pinned in `localthought/overlays`.
- Consumer `selection` objects (query overrides, OAuth security scheme
choice, trusted tenant-identity operation) for a specific catalog entry —
those are also authored in `localthought/overlays`' `catalog.json`.

If you find yourself wanting to add any of the above, stop — the right place
is an OpenAPI document or Overlay Specification document in
`localthought/overlays`, referenced from `catalog.json` there. See the
[Catalog section of the README](README.md#catalog) for how sources are pinned
and composed. `localthought/overlays` has its own validation scripts (e.g.
`scripts/validate_moneybird_metadata.rb`) for authoring correctness — extend
those instead of teaching this repo how to author a platform's data.

### Tests that use pinned platform fixtures are fine

The rule above is about *authoring* platform data and *branching on* platform
identity in runtime code — not about testing. A test — especially an
`#[ignore]`d one gated behind a real network fetch — that loads a real, pinned
`localthought/overlays` catalog revision and asserts facts about the
*composed result* (e.g. "the composed Moneybird document has N collections",
"every provider has non-empty OAuth scopes") is the correct way to prove the
generic load-and-compose pipeline actually produces the right document for
real inputs. This repo already does this: `src/identity_catalog_tests.rs` and
the pinned-catalog test in `src/catalog.rs` both load real composed
Google/GitHub/Moneybird data, with fixture provenance recorded in
`tests/identity-catalog/sources.json`. That's a different, complementary
layer from `localthought/overlays`' own authoring-time validation — this
repo's version proves the *proxy* composes real pins correctly at runtime,
not just that the overlay documents are internally well-formed.

The line: a test may *read and assert against* pinned platform data. Runtime
`src/` code may never *contain or branch on* it.

### What generic code may do

- Load and compose *any* catalog entry the same way, regardless of platform.
- Validate the *shape* of a catalog entry generically (e.g. "every OAuth
provider has at least one scope") without depending on which platform it
came from.
- Reference a pinned `localthought/overlays` catalog URL as the default
`CATALOG_PATH` (`src/config.rs`) — that's an opaque pointer, not platform
knowledge.
- Assert platform-specific facts about a pinned fixture in a test, to prove
the composition pipeline works end-to-end (see above).

### What belongs in `localthought/overlays` instead

- OpenAPI Overlay documents that add, fix, or complete response schemas,
CRUD/collection structure, pagination schemes, auth requirements, or
throttling limits for a specific API.
- Consumer `selection` objects for a specific catalog entry.
- Platform-specific validation scripts and fixtures for authoring correctness.

## Making a platform-specific fix

1. Make the change as an OpenAPI document or Overlay Specification document
in `localthought/overlays`, with its own validation there.
2. Publish and verify the immutable pins, then commit the updated root
`catalog.json` in `localthought/overlays`.
3. Bump the pinned `CATALOG_PATH` default in this repo's `src/config.rs` to
the new immutable revision (a one-line, platform-agnostic change) and
restart the service. Optionally add or extend a pinned-fixture test here
that asserts the newly composed document looks right — that's welcome.

Do not add a step that teaches this repo how to author the platform's data,
and do not make runtime `src/` code behave differently for one platform.

## Background

[PR #46](https://github.com/localthought/integration-proxy/pull/46) added an
`#[ignore]`d test asserting Moneybird-specific facts (collection counts,
throttling limits) about a pinned real catalog fixture in `src/catalog.rs`.
It was briefly reverted in
[PR #70](https://github.com/localthought/integration-proxy/pull/70) on
concern that this was Moneybird-specific code leaking into the generic proxy.
On inspection, it wasn't: the underlying data was authored correctly as
Overlay documents in `localthought/overlays`, and the test followed the same
pinned-fixture pattern already used elsewhere in this repo (see above) — it
just proved the proxy composes those pins correctly. PR #70 was closed as a
false alarm; this file exists so the actual boundary is written down instead
of re-litigated next time.
Loading