Skip to content

docs: repo-owned query contract and dev guidance (LFXV2-2015)#53

Open
josep-reyero wants to merge 11 commits into
mainfrom
feat/LFXV2-2015-query-service
Open

docs: repo-owned query contract and dev guidance (LFXV2-2015)#53
josep-reyero wants to merge 11 commits into
mainfrom
feat/LFXV2-2015-query-service

Conversation

@josep-reyero

@josep-reyero josep-reyero commented May 29, 2026

Copy link
Copy Markdown

Summary

Part of the LFX developer-AI fan-out (LFXV2-2015): repo-specific AI guidance moves out of the central lfx-skills plugin and into each owning repo, beside the code it describes. This PR lands this repo's share of that work.

📖 Read these first (they explain this PR)

This is one of ~15 coordinated fan-out PRs. Before reviewing, please read the three short docs that explain the whole change — they are the source of truth for the model and for what landed where:

Doc What it gives you
👉 Fan-out architecture The end-to-end model and the why behind it: the central-vs-repo split, the review lifecycle, and the per-repo tradeoffs. Start here.
👉 Fan-out owner guidance The new ownership model, central-vs-repo boundaries, and the review-lifecycle expectations.
👉 Rollout inventory Exactly what moved out of central and what landed in each repo — find this repo's section for the full scope.

Tracking epic: LFXV2-2015.

Why — the new architecture

Central finds the right owner and explains the shared platform; each repo explains itself. The central lfx-skills plugin keeps only genuinely-central surfaces: cross-repo routing, platform architecture, shared integration guidance, global workflows, and reviewer-agent distribution. Repo-specific implementation truth — conventions, generated-code boundaries, endpoint workflows, contracts, and chart defaults — now lives in the owning repo, where it changes together with the contracts, tests, and charts it describes.

This fixes the drift problem a central rulebook creates: it either grows until it contains repo-specific exceptions for every service, or stays short and goes stale. Where a repo has a review lifecycle, its repo-specific reviewer agents are packaged centrally (so they're available by name in any Claude runtime) but read evidence this repo owns — its CLAUDE.md, skills, rules, contracts, checklists, and review KB.

Changes in this repo

This repo owns query/read behavior consumed by Self Serve, newsletter, and others, so doc accuracy is high-value.

  • Repo-local skills: query-service-dev (post-page-shrinkage pagination, CEL-vs-OpenSearch split, batched access-check pattern) and query-resource (the per-resource query workflow).
  • Owned docs: docs/query-service-contract.md, docs/indexed-data-types.md (active queryable resource inventory, including member-service's b2b_org / b2b_org_settings / project_membership / key_contact), docs/resource-catalog.md (query cookbook).
  • CLAUDE.md routes platform/topology questions to the central skills and keeps query behavior repo-owned.

This branch is current with main.

Kept current with main (2026-06-11)

This branch was re-merged with the latest main and the guidance re-audited against the current code. The documented run commands now include the env vars the service actually requires at startup (PAGE_TOKEN_SECRET and the auth/org source settings), and references to a nonexistent make fmt target and 409 error mapping were removed. The indexed-type inventory and resource catalog were re-verified against all publishing repos.

Reference links

🤖 Generated with Claude Code

Land this repo's share of the LFX dev AI fan-out. Repo-owned development
conventions, contracts, and review evidence now live beside the code they
describe. Central lfx-skills retains cross-repo routing, platform
architecture, shared integration, global workflows, and reviewer-agent
packaging.

Inventory: lfx-architecture-scratch/2026-05-DevX-Time-to-Merge/fanout-repo-rollout-inventory.md
Ownership: lfx-architecture-scratch/2026-05-DevX-Time-to-Merge/fanout-repo-owner-guidance.md

Refs: https://linuxfoundation.atlassian.net/browse/LFXV2-2015
Signed-off-by: Josep Garcia-Reyero Sais <josepreyero@gmail.com>
…-service

Signed-off-by: Josep Garcia-Reyero Sais <josepreyero@gmail.com>

# Conflicts:
#	docs/resource-catalog.md
member-service now publishes b2b_org, b2b_org_settings, project_membership,
and key_contact index messages. Update the fan-out query docs to match the
current code:

- indexed-data-types.md: add a Members section with the four lfx.index.*
  subjects and source file; remove the stale "Not Currently Indexed" note.
- resource-catalog.md: drop the contradictory "Not Currently Queryable"
  section, add b2b_org_settings to the member row, correct the
  membership-by-status example to use filters (status is a data field, not a
  tag), and add key_contact and b2b_org_settings cookbook entries.
- query-service-contract.md: use $OPENSEARCH_INDEX in the debug curl instead
  of the non-default lfx-resources index name (default is resources).

Signed-off-by: Josep Garcia-Reyero Sais <josepreyero@gmail.com>
Copilot AI review requested due to automatic review settings May 29, 2026 14:49
@coderabbitai

coderabbitai Bot commented May 29, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: dafb86b5-bfa2-4d5a-8e06-a9d47db7e3e9

📥 Commits

Reviewing files that changed from the base of the PR and between a217b15 and 8a53b53.

📒 Files selected for processing (7)
  • .claude/skills/query-resource/SKILL.md
  • .claude/skills/query-resource/references/query-service-patterns.md
  • .claude/skills/query-service-dev/SKILL.md
  • .claude/skills/query-service-dev/references/go-development-conventions.md
  • CLAUDE.md
  • README.md
  • docs/query-service-contract.md
✅ Files skipped from review due to trivial changes (5)
  • .claude/skills/query-service-dev/references/go-development-conventions.md
  • CLAUDE.md
  • .claude/skills/query-resource/references/query-service-patterns.md
  • .claude/skills/query-service-dev/SKILL.md
  • docs/query-service-contract.md

Walkthrough

This PR adds comprehensive documentation for the query-service, including the canonical API contract, resource indexing patterns, usage examples, local development setup, and formalized Claude skills for AI-assisted codebase modifications.

Changes

Query Service Documentation and Guidance

Layer / File(s) Summary
Query Service API Contract
docs/query-service-contract.md
Canonical contract specification for GET /query/resources and GET /query/resources/count endpoints, covering parameters, response shapes, access control with FGA/NATS flow, OpenSearch field requirements, pagination rules, date filtering, CEL filter behavior, and clause-limit handling.
Resource Indexing and Discovery
docs/indexed-data-types.md
Maps queryable resource types to NATS subjects and publishing source files; documents discovery via backend constants, indexer subscription behavior, and extension patterns for new fields/types via IndexingConfig and lfx.index.<type> subjects.
Query Usage Examples and Resource Catalog
docs/resource-catalog.md
Updated resource type listings and query cookbook with practical examples for CEL filtering, filters clauses, filter_grants=direct, and specific patterns for project_document, committee_document, key_contact, and b2b_org_settings with tag-based scoping.
AI Agent Skills for Query Service
.claude/skills/query-resource/SKILL.md, .claude/skills/query-resource/references/query-service-patterns.md, .claude/skills/query-service-dev/SKILL.md, .claude/skills/query-service-dev/references/go-development-conventions.md
Formalized Claude skill definitions specifying allowed tools, Go development conventions (headers, logging, error handling, NATS usage, pagination, testing), query-specific behavioral invariants (OpenSearch vs CEL split, batched FGA checks, token semantics), and anti-patterns for query pipeline modifications.
Local Development and Environment Setup
CLAUDE.md, README.md
Environment variables (PAGE_TOKEN_SECRET, SEARCH_SOURCE, ACCESS_CONTROL_SOURCE, ORG_SEARCH_SOURCE, AUTH_SOURCE), mock and production run commands with Clearbit/NATS configuration, DI provider locations, API parameter documentation, build/test commands, and canonical contract references.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • linuxfoundation/lfx-v2-query-service#52: Overlapping modifications to docs/resource-catalog.md in member-service sections, including resource-type listings and membership-related query examples.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and specifically summarizes the main change: adding repo-owned query service documentation, contracts, and AI development guidance as part of the LFXV2-2015 fan-out initiative.
Description check ✅ Passed The description comprehensively explains the changeset context, architecture rationale, specific documentation and skill additions, governance changes, and verification status—all directly related to the PR's scope.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/LFXV2-2015-query-service

Comment @coderabbitai help to get the list of available commands and usage tips.

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.

Pull request overview

This documentation-only PR moves repo-owned query-service contract and AI/agent development guidance into this repository as part of the LFXV2-2015 fan-out effort.

Changes:

  • Adds canonical query-service contract docs covering API parameters, pagination, CEL filtering, access checks, and clause limits.
  • Adds indexed resource inventory and expands the resource query cookbook.
  • Adds repo-local Claude skills for query-service development and resource-query workflows, while updating README and CLAUDE routing guidance.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
README.md Points agents to repo docs, updates local run examples, and links detailed API contract docs.
CLAUDE.md Adds repo-local/central skill routing and moves detailed API behavior references into docs/.
docs/resource-catalog.md Expands queryable type catalog and cookbook examples.
docs/query-service-contract.md Adds canonical query-service API and implementation contract.
docs/indexed-data-types.md Adds active indexed type-to-service/NATS subject inventory.
.claude/skills/query-service-dev/SKILL.md Adds repo-local Go and query-pipeline development guidance.
.claude/skills/query-service-dev/references/go-development-conventions.md Adds deeper Go convention reference.
.claude/skills/query-resource/SKILL.md Adds query-resource workflow guidance.
.claude/skills/query-resource/references/query-service-patterns.md Points skill references to the canonical contract doc.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread docs/query-service-contract.md Outdated
Comment thread docs/query-service-contract.md Outdated
Comment thread docs/query-service-contract.md Outdated
@josep-reyero

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 1, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Address Copilot review on query-service-contract.md:

- Anonymous vs Authenticated table: clarify the FGA batch check covers
  non-public results only; public:true results skip the check (BuildMessage
  sets NeedCheck=false for them) for authenticated callers too.
- OpenSearch fields table: expand the `public` row to note it skips the FGA
  check for all callers and warn that setting it wrong exposes a private
  resource to everyone, not just anonymous users.
- CEL Filter limitation: remove the overstatement that an out-of-first-page
  match "won't be found"; CEL is applied per OpenSearch page, so the match is
  returned once the caller follows page_token. Keep the short-page caveat.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Josep Garcia-Reyero Sais <josepreyero@gmail.com>
@josep-reyero

Copy link
Copy Markdown
Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jun 1, 2026

Copy link
Copy Markdown
✅ Actions performed

Full review triggered.

@josep-reyero josep-reyero marked this pull request as ready for review June 1, 2026 14:15
Copilot AI review requested due to automatic review settings June 1, 2026 14:15
@josep-reyero josep-reyero requested a review from a team as a code owner June 1, 2026 14:15

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.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Comment thread README.md Outdated
Comment thread docs/query-service-contract.md Outdated
josep-reyero and others added 3 commits June 1, 2026 16:29
- README: PAGE_TOKEN_SECRET is required for any deployment, not only when
  paging; PageTokenSecret() fatals if unset and is called whenever a full
  page generates a token (even a first-page query).
- contract: page_token is generated by the query-service (encoding the
  OpenSearch search_after/sort cursor via paging.EncodePageToken), not by
  OpenSearch.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Josep Garcia-Reyero Sais <josepreyero@gmail.com>
- CLAUDE.md: align local run examples with the README — add the required
  PAGE_TOKEN_SECRET plus ORG_SEARCH_SOURCE, AUTH_SOURCE, and
  JWT_AUTH_DISABLED_MOCK_LOCAL_PRINCIPAL (defaults are jwt/clearbit, so
  the old mock command would fatal); expand the Configuration env-var list.
- query-service-dev skill + reference: there is no 'make fmt' target, use
  gofmt -w plus 'make lint'; pkg/errors has no NewConflict (constructors
  are NewValidation, NewNotFound, NewServiceUnavailable, NewUnexpected)
  and wrapError maps 400/404/503/500 only.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Josep Garcia-Reyero Sais <josepreyero@gmail.com>
Copilot AI review requested due to automatic review settings June 11, 2026 07:13

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.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.

Comment thread docs/query-service-contract.md Outdated
Reword the access-filtering note so it is clear that non-public
documents missing access_check_object or access_check_relation are
treated as unauthorized and excluded from results, since no
access-check message can be constructed for them. Previously the doc
said the query-service "skips it during access filtering", which
could be read as such resources bypassing checks and being returned.
Also align the field table rows for both fields.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Josep Garcia-Reyero Sais <josepreyero@gmail.com>
@dealako

dealako commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Hey @josep-reyero! Thanks for the work on this — the two-skill split and the query contract doc are both well-structured, and the documentation accuracy (verified against live code) is genuinely high quality.


👏 Nice work

  • Zero doc drift on implementation details: all function names, constants, CEL limits, and env var defaults spot-checked against live code — everything matches
  • Clean skill architecture: query-service-dev + query-resource split is clear, correctly defers cross-service routing to central LFX skills, no leakage either direction
  • Contract doc depth: pagination semantics, batched access-check pattern, NATS subjects, OpenSearch field requirements, and CEL behavior are all precise and match the implementation

Issue summary

Severity Count Items
🔴 Blocking 1 go.mod/go.sum dependency downgrades
🟡 Major 8 CEL pagination wording, public FGA semantics, principal context docs, README testing example, required-param validation undocumented, Clearbit timeout mismatch, DI guidance, duplicate catalog entry
⚪ Nit 7 H1 title mismatch, page_token attribution, bucket limit undocumented, missing env var, count endpoint in README, stale domain naming, PAGE_TOKEN_SECRET wording

Key findings

🔴 [C-001] go.mod/go.sum downgrades — This is a docs-only PR but the branch carries dependency downgrades vs main (e.g. go-chi/chi/v5 v5.2.4→v5.2.2, golang.org/x/crypto v0.52.0→v0.49.0). The branch diverged before main's security dep update (PR #59). Fix: merge latest main; go.mod/go.sum should have zero diff.

🟡 [M-001] CEL "won't be found" wording — A section implies CEL globally pre-filters results, but CEL runs per OpenSearch page. Callers paging through results will find matches; the current wording may cause them to stop early.

🟡 [M-002] public resource FGA semantics — Access control table treats public as anonymous-only, but authenticated callers also skip FGA for public: true resources. Two Copilot bot inline comments already on the PR capture this; both the anonymous and authenticated rows need the exception documented.

🟡 [M-003] Principal context docs say middleware; code says service layergo-development-conventions.md:68-84 states PrincipalContextID is set in internal/middleware, but it's actually populated in the service layer during token validation (cmd/service/service.go). Developers following this guidance will look in the wrong layer.

🟡 [M-004] README testing example won't compile — Constructor is NewResourceSearch (not NewResourceService), mock method is SetCheckAccessResponse (not SetAccessResult), and arity is wrong.

🟡 [M-005] Required-parameter validation not documentedresource_search.go rejects requests that don't include at least one of name, parent, type, tags, or filter_grants. Queries using only cel_filter or date_* will fail with an undocumented error.

🟡 [M-006] Clearbit timeout default contradicts codeREADME.md:347-351 labels CLEARBIT_TIMEOUT=30s as the default; NewConfig() defaults to 10s. The env-var table at line 201-204 is correct.


Bot comment reconciliation

The Copilot bot posted 6 inline comments. Two have already been addressed by recent commits (a217b15 resolves the access-filtering ambiguity; the PAGE_TOKEN_SECRET fatal-on-full-page clarification also appears to be in scope of recent fixes). Three remain open and are captured above as M-001 and M-002. One (page_token attribution to OpenSearch) is a nit.

CodeRabbit's most recent automated pass returned "no actionable comments" — consistent with the overall docs quality being high on the latest revision.


Final decision

🔴 Needs changes before approval — the go.mod downgrade is a security-sensitive blocker, and M-001–M-006 are accuracy issues that could mislead developers or fail to compile. Happy to re-review once the main merge and doc fixes are in.

@dealako dealako left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Changes requested — see review comment above for the full breakdown.

Copilot AI review requested due to automatic review settings June 12, 2026 14:25
@dealako

dealako commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

I updated the branch which should adress the go.mod/go.sum downgrades.

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.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.

Comment thread README.md Outdated
Comment thread CLAUDE.md Outdated
Comment thread docs/query-service-contract.md Outdated
Comment thread .claude/skills/query-service-dev/SKILL.md Outdated
josep-reyero and others added 2 commits June 15, 2026 13:14
Add the standard LFX copyright + MIT SPDX header to three git-tracked
markdown files under .claude/ that were missing it:

- .claude/skills/query-resource/SKILL.md (after frontmatter)
- .claude/skills/query-resource/references/query-service-patterns.md
- .claude/skills/query-service-dev/SKILL.md (after frontmatter)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Josep Garcia-Reyero Sais <josepreyero@gmail.com>
Address dealako CHANGES_REQUESTED items and open Copilot review threads.
All claims verified against current code.

- M-003: principal context is set in the Goa JWTAuth handler
  (cmd/service/service.go), not in internal/middleware (which only sets
  the request ID). Correct the Request Context guidance.
- M-004: fix the README testing example so it compiles: NewResourceSearch
  (not NewResourceService), SetCheckAccessResponse (not SetAccessResult),
  and the third resourceFilter argument.
- M-005: document the required-parameter rule (at least one of name,
  parent, type, tags, filter_grants) in the contract doc and README.
- M-006: README Clearbit example default is 10s, matching NewConfig()
  (was incorrectly 30s).
- Copilot: PageTokenSecret takes a context argument; fix call form in
  README and CLAUDE.md.
- Copilot: CEL program cache is a TTL-bounded map (100 max, 5-min TTL,
  no LRU eviction), not an LRU cache; fix contract doc and SKILL.md.
- Nits: contract doc H1 is now "Query Service Contract"; add the
  /query/resources/count endpoint to the README; document the
  CLEARBIT_AUTOCOMPLETE_BASE_URL env var; document the aggregation
  bucket cap (DefaultBucketSize = 100) for count queries.

M-001 (CEL per-page wording) and M-002 (public skips FGA for all callers,
both table rows) were already addressed in earlier commits (5cca89e) and
remain correct in the current docs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Josep Garcia-Reyero Sais <josepreyero@gmail.com>
@josep-reyero

Copy link
Copy Markdown
Author

@dealako thanks for the thorough review. Pushed 553eec8 (license headers) and 8a53b53 (review feedback). Every claim re-verified against current code on the branch.

C-001 (go.mod/go.sum downgrades) — Resolved. Merged your main-update; git diff origin/main -- go.mod go.sum is now empty (zero diff).

Major:

  • M-001 (CEL "won't be found" wording) — Already fixed in 5cca89e; the contract doc states CEL applies per OpenSearch page and tells callers to keep paginating until page_token is absent. No further change needed.
  • M-002 (public skips FGA for all callers) — Already fixed in 5cca89e; documented in both rows of the Anonymous vs Authenticated table (anonymous = Skipped; authenticated = "non-public results only, public: true results skip the check") and in the public field row with the exposure warning. Verified against BuildMessage (sets NeedCheck=false for any public result). The two Copilot threads on this were already resolved.
  • M-003 (PrincipalContextID layer) — Fixed. Corrected go-development-conventions.md: the principal is set in the Goa JWTAuth handler (cmd/service/service.go) during token validation, not in internal/middleware/ (which only sets the request ID).
  • M-004 (README testing example) — Fixed. Now uses NewResourceSearch (3 args incl. resourceFilter), SetCheckAccessResponse(map[string]string{...}); compiles against the real mock + constructor.
  • M-005 (required-parameter validation) — Fixed. Documented the "at least one of name/parent/type/tags/filter_grants" rule (and the 400 it returns) in both the contract doc and README, citing validateSearchCriteria.
  • M-006 (Clearbit timeout default) — Fixed. README example now shows CLEARBIT_TIMEOUT=10s, matching NewConfig() (empty → "10s"); the env-var table was already correct.

Nits:

  • Contract doc H1 changed to "Query Service Contract".
  • Added the GET /query/resources/count endpoint to the README API section.
  • Added the missing CLEARBIT_AUTOCOMPLETE_BASE_URL env var to the README Clearbit list.
  • Documented the count aggregation bucket cap (DefaultBucketSize = 100).
  • page_token attribution and PAGE_TOKEN_SECRET "required for any deployment" wording were already addressed in 7a9a508.

Open Copilot threads (latest pass) — all four addressed in 8a53b53 and resolved: PageTokenSecret(ctx) call form in README and CLAUDE.md; CEL cache corrected from "LRU" to "TTL-bounded map (100 entries, 5-min TTL, no LRU eviction)" in the contract doc and SKILL.md.

Deferred (ambiguous, no clear target in current code): the "stale domain naming" and "duplicate catalog entry" items from the summary table — I could not pin them to a specific stale string or duplicate row in the current docs. Happy to fix if you can point to the exact location.

Also added the missing SPDX/MIT headers to the three .claude/ skill docs that lacked them (553eec8).

@josep-reyero josep-reyero requested a review from dealako June 15, 2026 11:56
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.

3 participants