Skip to main content

AppView Plans

What is the Layers AppView?

An ATProto appview is a read-only indexing service that subscribes to the protocol's firehose, extracts records it cares about, and serves them back through query endpoints. The appview never owns user data; all pub.layers.* records live in user-controlled Personal Data Servers (PDSes). If the appview's database disappears, nothing is lost because every record can be rebuilt from the firehose.

The Layers appview indexes all 26 pub.layers.* record types, maintains full-text and faceted search indexes, builds a knowledge graph from cross-references, and exposes the results through XRPC and REST APIs.

Architecture at a Glance

The appview runs as two separate processes, following Chive's two-process architecture:

  • API Server (src/index.ts): serves XRPC and REST queries, starts scheduled jobs
  • Firehose Indexer (src/indexer.ts): consumes the AT Protocol firehose, writes to all storage backends

Record Type Coverage Matrix

Every pub.layers.* record type is indexed into one or more storage backends. PostgreSQL is the source of truth for all types. Elasticsearch and Neo4j are populated selectively based on query requirements.

Record TypePGESNeo4jNotes
expression.expressionyesyesyesFull-text search on text, graph node for cross-refs
segmentation.segmentationyesToken arrays stored in PG, queried via expression
annotation.annotationLayeryesyesyesAnnotations normalized to rows in PG, nested in ES for faceted search, per-annotation nodes in Neo4j
annotation.clusterSetyesyesCluster membership edges in Neo4j
ontology.ontologyyesyesSearchable by domain and name
ontology.typeDefyesyesyesType hierarchy edges in Neo4j
corpus.corpusyesyesSearchable by name, language, license
corpus.membershipyesyesCorpus-expression edges in Neo4j
resource.entryyesyesLexical search on lemma and form
resource.collectionyesyesSearchable by name
resource.collectionMembershipyesJoin table
resource.templateyesTemplate storage
resource.fillingyesFilling storage
resource.templateCompositionyesComposition storage
judgment.experimentDefyesyesSearchable by measure/task type
judgment.judgmentSetyesLinked to experiment
judgment.agreementReportyesLinked to experiment
alignment.alignmentyesyesSource-target edges in Neo4j
graph.graphNodeyesyesyesPrimary Neo4j content, ES for node search
graph.graphEdgeyesyesPrimary Neo4j content
graph.graphEdgeSetyesyesExpanded to individual edges in Neo4j
persona.personayesyesSearchable by domain and kind
media.mediayesyesSearchable by modality
eprint.eprintyesyesSearchable by identifier, title
eprint.dataLinkyesyesEprint-corpus edges in Neo4j
changelog.entryyesyesSearchable by subject, collection, version

Source Directory Layout

The src/ directory follows Chive's layered + feature-based hybrid organization:

src/
├── api/ # Hono handlers (xrpc/, rest/), middleware, openapi
├── atproto/ # AT Protocol client, repository access, errors
├── auth/ # OAuth, JWT, DID, MFA, WebAuthn, zero-trust, authorization, scopes, session
├── config/ # Configuration management
├── jobs/ # Scheduled interval-based jobs (staleness, reconciliation)
├── lexicons/ # Generated TypeScript types from lexicon JSON
├── observability/ # Logger, telemetry, tracer, metrics-exporter
├── plugins/ # core/, builtin/, sandbox/
├── services/ # Business logic (indexing/, search/, enrichment/, import/, etc.)
├── storage/ # postgresql/, elasticsearch/, neo4j/, redis/ adapters
├── types/ # models, interfaces, errors.ts, result.ts
├── utils/ # Shared utilities
├── workers/ # BullMQ worker implementations
├── index.ts # API server entry point
└── indexer.ts # Firehose consumer entry point

Design Goals

Follow Chive's Proven Architecture

The Layers appview follows Chive's production architecture closely. Chive is a running ATProto appview for scholarly eprints that has already solved the hard infrastructure problems (firehose subscription with cursor-based resumption, multi-database indexing, dual XRPC/REST APIs, BullMQ job queues, and Kubernetes deployment). Layers adopts the same technology stack, patterns, and operational practices, including the two-process split, layered directory structure, storage adapter interfaces, and dependency injection via tsyringe.

Type-Safe Error Handling

All fallible operations return Result<T, LayersError> instead of throwing exceptions, following Chive's Result<T, E> pattern. The LayersError hierarchy provides typed error classification:

  • ComplianceError — ATProto compliance violations (write to PDS, blob storage, non-rebuildable state)
  • NotFoundError, ValidationError — client errors
  • AuthenticationError, AuthorizationError, RateLimitError — auth/access errors
  • DatabaseError, ServiceUnavailableError — infrastructure errors
  • PluginError, SandboxViolationError — plugin system errors

See Technology Stack for the full error handling architecture.

Adapt for Layers-Specific Complexity

Where Layers diverges from Chive:

  • 26 record types (vs Chive's ~7) require dependency-aware ingestion ordering and more sophisticated queue topology
  • Discriminated annotation model (kind/subkind/formalism) requires three-dimensional faceted search in Elasticsearch
  • Dense cross-referencing (sourceUrl, sourceRef, eprintRef, graphEdge targets, knowledgeRefs) requires a dedicated cross-reference index and Neo4j edge graph
  • Embedded annotation arrays (an annotationLayer can contain hundreds of individual annotations) require careful normalization decisions per storage backend
  • Format import pipeline (CoNLL, BRAT, ELAN, TEI, etc.) extends the plugin system beyond Chive's harvester model
  • Annotation workflow RBAC (annotator, adjudicator, corpus manager) requires more granular authorization than Chive's publish/read model

Bleeding-Edge Infrastructure

The appview targets 2026 best practices:

  • OpenTelemetry 1.x stable for unified observability (traces, metrics, logs)
  • Distroless container images (gcr.io/distroless/nodejs22-debian12) for minimal attack surface
  • Sigstore cosign for container image signing and supply chain verification
  • GitOps via ArgoCD/Flux for declarative, auditable deployments
  • Zero-trust security with mTLS between services, DPoP token binding, and passkeys-first authentication
  • WebTransport monitored as a future firehose transport alternative (multiplexed streams, better congestion control)

Page Directory

PageContent
Technology StackRuntime, frameworks, databases, and tooling with version pins and decision rationale
Database DesignPostgreSQL schema, Elasticsearch mappings, Neo4j graph model, Redis data model
Firehose IngestionSubscription, filtering, queue topology, dependency ordering, dead letter queue
API DesignXRPC + REST endpoints, search, composite queries, OpenAPI
Indexing StrategyPer-record-type indexing, annotation normalization, cross-reference extraction
Query and DiscoveryUse cases, query patterns, graph traversal, caching
AuthenticationOAuth 2.0, JWT sessions, RBAC, MFA
Background JobsWorkers, enrichment, format import, maintenance
ObservabilityLogging, tracing, metrics, dashboards, alerting
DeploymentDocker, Kubernetes, database deployment, CI/CD, backup
Testing StrategyUnit, integration, compliance, E2E, performance
Plugin SystemSandboxed plugins, format importers, harvesters

See Also