OEFF 2026 Data Architecture

Spec v2 — Updated March 27, 2026
For the OEFF core team · Airtable Base appvUfaPd9ejb5fHb

See also: Architecture Overview — visual map of the data model, decisions, and data flow

1. Principles

Core Insight

"The most specific our data will ever get is by event."

2. Canonical Data Sources

Four sources own the data. Everything else derives from them.

SourceLayerOwnsEdited By
OEC Active Roadmap
Google Sheet (OEC workspace)
Planning Program timeline, milestones, who-owns-what Team
Host-Venue-Film-Screening Tracker
Google Sheet
Operations Confirmed schedule, contacts directory, venue AV/accessibility, film licensing Operations team
Communications + Engagements Tracker
Google Sheet
Communications Every outbound email/invite, webinars, visioning calls, ownership chain Communications lead
Filmmaker operational context
Maintained by Technical Coordinator
Film Ops Delivery status, licensing conversations, caption QC, contact context Technical Coordinator

Conflict Rule

If data in Airtable conflicts with data in a canonical sheet, the sheet wins. Always. Airtable is a reflection, not a source.

3. Data Flow

OEC Roadmap Tracker Sheets Film Context oeff-v2-enrich.py (one-way, idempotent) Airtable v2 Base Host Guide Eventbrite Deliverables Dashboards

Sync is one-way and idempotent. The enrichment script matches records by name or email before creating, so it is safe to run daily. Venue name aliases handle naming drift between sheets and Airtable.

4. Schema: 14 Tables Across 4 Layers

Layer 1 Core — Persistent, Year-Over-Year

Seasons · Contacts · Organizations · Venues · Films

Layer 2 Relational — Season-Specific

Events · Assignments

Layer 3 Asset Pipeline — Operational

Assets · Asset Versions · Deliverables · Deliveries

Layer 4 Supporting — Operational Memory + Turnover Insurance

Comms Log · Procedures · Routing Rules

The base also contains Sponsors (legacy from v1, may be consolidated into Organizations) and Host Submissions (form responses from hosts). These sit outside the 14-table architecture.

Layer 1: Core

Persistent across festival years. Records accumulate knowledge over time.

TablePurposeKey Fields
SeasonsOne record per festival editionName, Start/End Date, Status, Schema Freeze Date
ContactsAll people. Biographical info only — roles are in Assignments.Name, Email, Phone, Relationship Type
OrganizationsHost orgs, sponsors, partners, production companiesName, Type, Website, Address
VenuesPhysical spaces — capacity, AV equipment, accessibilityName, Address, Capacity, AV Equipment, ADA Accessible, Technical Tier, Classification
FilmsOne record per title, persistent. Licensing and captions tracked here.Title, Runtime, Director, Year, Format, Caption Status, Licensing Notes

Layer 2: Relational

Season-specific. Created fresh each year.

TablePurposeLinks To
EventsOne record per screening/event. Links venue, film, season.Season, Venue, Film
AssignmentsJunction table: one Contact + one context + one RoleContact, Organization, Venue, Film, Event

Layer 3: Asset Pipeline

Populated during operations. Tracks files from request through delivery.

TablePurposeLinks To
AssetsOne record per logical asset (screening copy, poster, SRT file)Season, Film, Event
Asset VersionsOne record per file version — enables QC tracking and rollbackAsset
DeliverablesPackaged outputs for stakeholders (screening packets, presenter guides)Season, Event, Source Assets
DeliveriesRecipient-level tracking: what was sent to whom, when, howDeliverable, Recipient (Contact)

Layer 4: Supporting

Operational memory. Depends on Layer 1 (Contacts) but not Layer 2 (Events). Persistent across seasons.

TablePurposeLinks To
Comms LogSignificant communications: commitments, agreements, follow-upsContact
ProceduresRunbooks and SOPs
Routing Rules"If X happens, do Y, person Z owns it" — explicit decision treesProcedure

5. The Junction Pattern (Assignments)

Assignments replaced four separate tables from the old base (Host Contacts, Film Contacts, Participants, Partners) with a single junction table.

How It Works

An Assignment links one Contact to one context (an Organization, Venue, Film, or Event) and gives them a Role in that context.

Example records:

ContactContextRolePriority
Ben KadlecTriton College (Venue)Host ContactPrimary
Colleen ThurstonDrowned Land (Film)FilmmakerPrimary
Michelle SvensonDrowned Land (Film)FilmmakerSecondary
Staff MemberBeyond Zero at Trinity Lutheran (Event)Festival StaffPrimary

What this enables:

6. Field Reference

Events Layer 2

Assignments Layer 2

Venues Layer 1

Films Layer 1

7. Sync Pipeline

One script handles all synchronization: oeff-v2-enrich.py

StepSourceTarget TableWhat It Does
venuesTracker → Venues tabVenuesUpdates AV equipment, accessibility, addresses, capacity
filmsTracker → Films tabFilmsAdds licensing status/fees, runtime, format, caption status
eventsTracker → Screenings tabEventsUpdates/creates confirmed screenings with dates, times, fees, POC
directoryTracker → Directory tabContacts + AssignmentsAdds new contacts, creates role assignments
commsComms + Engagements TrackerComms LogSyncs email pipeline + webinar/meeting tracking
filmmakerLocal staging JSONFilms + Comms LogPushes filmmaker status updates, archives staging file
fix-gapsHardcoded listsFilms + VenuesCreates records the sheets reference but v2 lacks
# Typical usage
python3 ~/tools/oeff-v2-enrich.py                     # dry run all steps
python3 ~/tools/oeff-v2-enrich.py --apply              # sync everything
python3 ~/tools/oeff-v2-enrich.py --step comms --apply # just comms
python3 ~/tools/oeff-v2-enrich.py --step filmmaker --apply  # push film updates

Idempotent

Every step checks for existing records before creating. The script is safe to run daily, weekly, or on-demand. Running it twice produces the same result as running it once.

8. Record Counts (as of March 16, 2026)

TableRecordsNotes
Seasons12026 (Apr 22–27)
Contacts188Deduplicated across 4 sources by email
Organizations50Sponsors + host organizations
Venues10421 with full AV/accessibility data from tracker sheet
Films15All with licensing data from tracker sheet
Events19022 with confirmed April dates, times, ticket prices
Assignments217Host contacts, AV contacts, filmmakers, panelists
Comms Log5032 communications + 18 engagements
Assets0Populated during operations
Asset Versions0Populated during operations
Deliverables0Populated during operations
Deliveries0Populated during operations
Procedures0Added as SOPs are written
Routing Rules0Added as decision trees are documented

9. Airtable API Limitations

Determined through implementation. Formulas, rollups, and lookups require manual UI work.

OperationREST APIScripting ExtensionUI Only
Create link field
Create text/number/select field
Create formula field
Create rollup field
Create lookup field
Create count field
PATCH rollup link sourceN/A
PATCH formula expression
Populate link field values
Read schema/metadata✓ (partial)
Delete table

10. What We Didn't Migrate

The old Airtable base had 16 tables. Several were replaced by the junction pattern or the asset pipeline. Their data is preserved in CSV backups but not carried forward structurally.

Old TableReplaced ByWhy
Host ContactsContacts + Assignments (Role = Host Contact)Junction pattern eliminates per-type contact tables
Film ContactsContacts + Assignments (Role = Filmmaker)Same
ParticipantsContacts + Assignments (Role = Panelist, etc.)Same
PartnersOrganizations (Type = Partner)Partners are orgs with a type tag, not a separate entity
Media AssetsAssets + Asset VersionsVersion tracking and QC pipeline added
Packet QADeliverables + DeliveriesRecipient-level tracking replaces packet-level QA
RecordingsComms Log (engagements with recording URLs)Recordings are attributes of engagements, not standalone
Host ConfirmationsAssignments view (filter: Role = Host Contact)A view, not a table

Updated March 27, 2026. Airtable base appvUfaPd9ejb5fHb.
Sync scripts: oeff-v2-build.py, oeff-v2-populate.py, oeff-v2-enrich.py