Skip to content

Support reflecting more than one platform in a single run - #22

Merged
michielbdejong merged 3 commits into
mainfrom
claude/reflector-rs-issue-15-su8wlb
Sep 7, 2026
Merged

michielbdejong merged 3 commits into
mainfrom
claude/reflector-rs-issue-15-su8wlb

Conversation

@michielbdejong

Copy link
Copy Markdown
Contributor

Summary

Works towards #15 ("Add a few more platforms"): reflector-rs can now reflect several read-only platforms in one run instead of just GitHub.

  • spec/ restructured to one subfolder per platform: spec/github/ (moved) and a new spec/google-calendar/, each with its own OpenAPI document and overlays/{auth,pagination,crud-causality}.yaml.
  • New PLATFORMS environment variable. Unset, behavior is unchanged — one github platform, configured exactly as before from the historical unprefixed variables (OPENAPI_DOCUMENT, API_TOKEN/GITHUB_TOKEN, API_CONSTANTS, …). Set to a comma-separated list (e.g. PLATFORMS=github,google-calendar), every named platform instead reads its own <PLATFORM>_-prefixed variables (GITHUB_API_TOKEN, GOOGLE_CALENDAR_API_TOKEN, …), with built-in defaults for github and google-calendar and explicit configuration required for anything else.
  • main.rs now loops over the configured platforms, syncing each into the same store; the GitHub-specific interactive OAuth fallback applies only to a platform actually named github. One platform failing (bad credential, network error) is logged and skipped rather than aborting the whole run; the process exits non-zero only if something failed.
  • A real second platform: google-calendar. A narrowed, read-only OpenAPI document (calendar-list entries and events) plus overlays, adapted from the fuller document localthought/reflector already vendors for the TypeScript engine — notably using a plain pageToken pagination scheme rather than that engine's incrementalSync, since syncables-rs's pagination extension only recognizes pageNumber/pageToken/nextLink. Verified end-to-end against the real API (anonymous credentials, so the requests were rejected, but the document parsed and the resource model — calendar-list entries providing each event's calendarId context — walked correctly).
  • Clockify (also requested in the issue) turned out to need upstream work first: its API authenticates with an x-api-key header (an OpenAPI apiKey scheme), and syncables::Credentials in localthought/syncables-rs only models Authorization: Bearer today. Documented as a concrete blocker in the README rather than adding it without working auth.
  • README (Reflecting more than one platform section, configuration table, vendored-documents section) and .env.example updated to match, plus a session log under docs/ai-logs/sessions/ per this repo's AI-disclosure convention.

Test plan

  • cargo fmt -- --check
  • cargo test (46 tests)
  • cargo clippy --all-targets -- -D warnings
  • cargo build
  • cargo build --target wasm32-unknown-unknown --lib
  • cargo clippy --target wasm32-unknown-unknown --lib -- -D warnings
  • Manual smoke test: default single-platform run (github, unset PLATFORMS) still syncs as before.
  • Manual smoke test: PLATFORMS=google-calendar — document/overlays parse, resource model derives correctly, requests are constructed against the real Google Calendar API (anonymous credentials, so rejected with 401/403 as expected).

🤖 Generated with Claude Code

https://claude.ai/code/session_015uMtEr3myMSRyBMaSWP3k5


Generated by Claude Code

Restructures spec/ into one subfolder per platform and adds a PLATFORMS
environment variable: unset, behavior is unchanged (one `github` platform
from the historical unprefixed variables); set, each named platform reads
its own <PLATFORM>_-prefixed OpenAPI document/overlays/token/constants,
falling back to built-in defaults for `github` and a new `google-calendar`
platform (read-only: calendar-list entries and events). main.rs now syncs
every configured platform into the same store, applying the GitHub OAuth
fallback only to a platform actually named `github`.

Clockify, also requested in the issue, needs syncables-rs to support
apiKey-header credentials first (it only models Authorization: Bearer
today) — documented in the README rather than added without working auth.

Closes #15.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015uMtEr3myMSRyBMaSWP3k5
Merging origin/main (#21, which grouped every record under one Drive/
Document/Table per imported dataset) auto-merged cleanly but left
Config::dataset_namespace() referencing a `constants` field that this
branch had already moved onto each PlatformConfig, and a single
AtomicStorage shared across all configured platforms — which would
collide every platform's records into the same dataset instead of
keeping each platform's own Drive.

Moves dataset_namespace() onto PlatformConfig (derived from that
platform's own constants) and builds one AtomicStorage per platform,
sharing the same underlying Db, matching the one-AtomicStorage-per-
dataset pattern #21 already established for a single run with multiple
namespaces.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015uMtEr3myMSRyBMaSWP3k5
@michielbdejong
michielbdejong merged commit ec3553b into main Sep 7, 2026
1 check passed
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