Skip to content

Merge v0.10.0 - #132

Open
Kzoeps wants to merge 37 commits into
stagingfrom
main
Open

Kzoeps wants to merge 37 commits into
stagingfrom
main

Conversation

@Kzoeps

@Kzoeps Kzoeps commented Aug 22, 2026

Copy link
Copy Markdown
Member

No description provided.

Kzoeps and others added 12 commits July 1, 2026 16:50
…n-gate

# Conflicts:
#	internal/database/migrations/migrations_test.go
Reject duplicate filesystem Lexicon IDs, return reliable Lexicon timestamps, and cover existing-row migration upgrades. Bound CAR error details and apply the remaining focused test, formatting, and operator-documentation fixes.
Filter endorsement closure inputs to valid records and align local API smoke checks with raw validation metadata and typed visibility.
…n-gate

# Conflicts:
#	.agents/skills/hyperindex/references/schema-reference.md
#	cmd/hyperindex/main.go
#	internal/graphql/schema/builder.go
#	internal/graphql/schema/builder_test.go
#	internal/graphql/subscription/handler.go
#	internal/graphql/subscription/handler_test.go
#	internal/graphql/subscription/pubsub.go
@vercel

vercel Bot commented Aug 22, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
hyperindex-atproto-client Ready Ready Preview Oct 28, 2026 8:39am UTC
hyperindex-client Ready Ready Preview Oct 28, 2026 8:39am UTC

Request Review

@coderabbitai

coderabbitai Bot commented Aug 22, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@greptile-apps

greptile-apps Bot commented Aug 22, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

The PR appears safe to merge.

Findings

  1. P2 Startup guidance remains stale ▶

Summary

The PR merges the v0.10.0 validation and record-history work.

  • Adds startup-snapshot record validation and gates typed GraphQL and subscriptions to valid records.
  • Adds opt-in record version history, migrations, ingestion integration, and the recordHistory query.
  • Bundles required Lexicons and aligns Jetstream, backfill, admin, and frontend behavior with the startup snapshot.
Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Filesystem and database Lexicons] --> B[Build fixed startup validator]
  B --> C[Refresh stored validation metadata]
  C --> D[Start GraphQL and subscriptions]
  B --> E[Jetstream, Tap, and backfill validation]
  E --> F[Store raw records with validation status]
  F --> G[Generic raw queries]
  F -->|valid only| H[Typed GraphQL and subscriptions]
  E --> I[Optional record version history]
  I --> J[recordHistory query]
Loading

Reviews (4) · Last reviewed commit: "Merge pull request #137 from GainForest/..."

Comment thread cmd/hyperindex/main.go
Comment on lines +771 to +774
svc.validator, err = validation.NewValidatorFromLexiconBytes(savedLexicons)
if err != nil {
return nil, fmt.Errorf("failed to build startup Lexicon snapshot: %w", err)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Startup guidance remains stale

The fixed startup Lexicon snapshot and validation-refresh workflow change configuration and migration behavior, but AGENTS.md still omits the restart-only application model and startup refresh requirements, leaving future operational and maintenance work based on stale repository guidance.

Context Used: AGENTS.md (source)

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Collections listed in RECORD_HISTORY_COLLECTIONS (exact NSIDs or prefix.*
patterns, Tap mode) now keep every observed version in a new record_version
table: one row per distinct CID plus delete tombstones, written before the
current-state upsert so Tap redelivery keeps both consistent and repeats are
no-ops. Startup seeds a baseline row per existing record without history.
The root recordHistory(uri, first) GraphQL query returns versions oldest
first. Off by default.

Motivation: GainForest needs the label edit history of observations
(app.gainforest.dwc.occurrence), meaning who changed a species name and
when. Public Jetstream misses most certified.one events, so the indexer's
Tap stream is the only reliable source.
- Dedupe on a version key: the CID, a sha256 of the body when Tap sends no
  CID, or delete:<cid> for tombstones. CID-less edits no longer collapse into
  one version and redelivered deletes are no-ops.
- Write the delete tombstone before removing the record and fail the event if
  it cannot be written, so Tap retries instead of losing the tombstone.
- recordHistory pages with an `after` version id; `first` must be 1-500.
- Switch history on only after baseline seeding succeeds, so a failed seed
  never leaves records whose baseline the next seed would skip.
- Docs: deletes have a null value, paging, history stays queryable after a
  collection is removed.
Opt-in record version history (recordHistory query)
Deleting a record now removes its stored versions (instead of adding a
tombstone), and PurgeActorData removes an account's versions together with
its records, so deleted, deactivated or taken-down accounts leave no
queryable past versions. The purge runs on every delete delivery and even
for collections no longer tracked, so history recorded earlier is never
stranded. Migration 016 indexes record_version(did) for account purges.
Kzoeps and others added 3 commits October 28, 2026 00:41
Prod stores app.gainforest.organization.getIndexedOrganizations (main type
query). The startup Lexicon gate rejected it with 'unsupported main definition
type: query' and refused to boot. Query/procedure/subscription/permission-set
lexicons never describe stored records, so skip them with a warning. Unknown
types still fail closed.
…artup

validation: skip non-record lexicons when building startup snapshot
Kzoeps and others added 5 commits October 28, 2026 12:59
Validated typed queries sorted or filtered by createdAt compiled to
ORDER BY json->>'createdAt', which bitmap-scanned and sorted every valid
row in the collection. On app.gainforest.ac.audio this took 2-6s under
load and pushed www feed requests past their timeouts.

For collections whose Lexicon makes top-level createdAt a required
datetime, map the sort and full-datetime filters to record_created_at so
Postgres walks idx_record_timeline_valid and stops at LIMIT. The write
path keeps first-seen createdAt, matching recordTimeline.
Lexicon allows const on boolean, integer, and string fields. The parser
decoded const as a string, so saved lexicons such as app.bsky.embed.record
(viewBlocked.blocked: true) failed to parse and now abort startup while
building the startup Lexicon snapshot.
pgx caches prepared statements. Once PostgreSQL switches one to a generic
plan it cannot tell that the validation_status bind parameter equals
'valid', so it falls back to idx_record_timeline_collection_created and
filters out invalid rows one by one instead of using
idx_record_timeline_valid. Inline the constant on the sorted and reversed
connection queries and add a forced-generic-plan regression test.
graphql, records: sort createdAt by indexed record_created_at
lexicon: accept boolean and integer const values
Kzoeps and others added 2 commits October 28, 2026 14:33
RECORD_VALIDATION_ENABLED turns write-time Lexicon validation off; records
are stored as unvalidated with a NULL lexicon_hash so the startup refresh
reclassifies them once validation is re-enabled.

TYPED_GRAPHQL_VALID_ONLY turns off the typed GraphQL validity filter for
queries, subscriptions, profile hydration, and endorsement closure. Typed
record objects now expose validationStatus and validationError so clients
can tell rows apart. Disabling validation requires disabling the filter.
validation: add env toggles for record validation and typed filter

This branch had an error being deployed

1 failed and 4 active deployments
Preview – hyperindex-client — e0635fd3 Deployed Oct 28, 2026 by vercel[bot]
Preview – hyperindex-atproto-client — e0635fd3 Deployed Oct 28, 2026 by vercel[bot]
hyperindex-v2-setup / test — e0635fd3 Deployed Oct 28, 2026 by railway-app[bot]
hyperindex / test — e0635fd3 Deployed Oct 28, 2026 by railway-app[bot]
hyperindex-v2-setup / production — e0635fd3 Deployed Oct 28, 2026 by railway-app[bot]
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