Tideswell / Jester / Zuiyo → Terra Parity Matrix
How the Current Stack Works
Before comparing, it helps to understand that “Tideswell” is actually three systems working together:Form Field Types
| Field Type | Tideswell | Jester Stores As | Terra | Status | Notes |
|---|---|---|---|---|---|
| Single line text | SingleLineQuestion | TEXT | Text field | ✅ Parity | |
| Multi-line text | SingleLineQuestion (multiLine flag) | TEXT | Text field (multiline variant) | ✅ Parity | |
| Radio / checkbox | ChoiceQuestion | TEXT[] array | Choice field | ✅ Parity | |
| Dropdown | ChoiceQuestion (displayFormat: dropdown) | TEXT[] array | Choice field (dropdown variant) | ✅ Parity | |
| Date | DateQuestion | DATE | Date field | ✅ Parity | Both support min/max date constraints |
| Number | NumericalQuestion | NUMERIC | Number field | ✅ Parity | Both support integer, whole, currency, decimal |
| Address | AddressQuestion | 5+ TEXT columns | Address field | ✅ Parity | Both use Smarty for validation |
| File upload | FilesQuestion | file_id, orig_name, url | Files field | ✅ Parity | Tideswell: Google Drive only. Terra: Supabase Storage + Google Drive |
| ID verification | IdVerificationQuestion | 60+ Plaid columns | Plaid IDV field | ✅ Parity | |
| Bank verification | BankVerificationQuestion | account_id, routing, mask | Plaid Bank field | ✅ Parity | |
| Info / display block | InfoQuestion | Not stored | Info block | ✅ Parity | Terra adds markdown + alert variants |
| Grouped section | GroupedQuestion (nested container) | N/A | ⚠️ Verify | 🔲 Validate | Tideswell supports nested question groups — confirm Terra handles same nesting depth |
| Repeated / referenced question | RepeatedQuestion (references another question by name) | N/A | ❌ Not found | 🔴 Gap | Tideswell can reference an existing question elsewhere in the form. Terra equivalent unclear |
| Signature | Not in Tideswell | N/A | Signature field | ➕ Terra extra | |
| Payment | Not in Tideswell | N/A | Payment field | ➕ Terra extra |
Conditional Logic
| Capability | Tideswell | Terra | Status | Notes |
|---|---|---|---|---|
| AND groups | ✅ | ✅ | ✅ Parity | |
| OR groups | ✅ | ✅ | ✅ Parity | |
| Greater than (numeric) | FLOAT_GT | gt, gte | ✅ Parity | |
| Less than (numeric) | FLOAT_LT | lt, lte | ✅ Parity | |
| Equals / not equals | Implied | eq, neq | ✅ Terra more | Terra explicit |
| Array intersection (multi-select) | INTERSECTS_WITH | in | ✅ Parity | |
| Text contains / starts / ends | ❌ | contains, starts_with, ends_with | ➕ Terra extra | |
| Age-based rules | ❌ | minAge, maxAge | ➕ Terra extra | |
| Field exists check | ❌ | exists | ➕ Terra extra | |
| Recursive nesting | ✅ | ✅ | ✅ Parity | |
| Reference another question’s value | ✅ (answerRaw by name) | ✅ | ✅ Parity | |
| Legacy logicInRules (2D array) | ✅ (older forms) | ❌ | 🔴 Gap | Some older forms may use this. Check which active forms rely on it |
Submission Storage & Data Integrity
| Capability | Tideswell/Jester | Terra | Status | Notes |
|---|---|---|---|---|
| Submission ID | ✅ <formId><8chars> | ✅ | ✅ Parity | |
| Status tracking | ✅ incomplete / submitted / withdrawn | ✅ | ✅ Parity | |
| Timestamp tracking | ✅ createdAt, submittedAt | ✅ | ✅ Parity | |
| IP geolocation on submit | ✅ address, country, city, lat, lon | ✅ | ✅ Parity | |
| Language on submit | ✅ | ✅ | ✅ Parity | |
| Outcome field (admin-set, visible to applicant) | ✅ | ⚠️ Verify | 🔲 Validate | Tideswell has a dedicated outcome field admins set per submission. Verify Terra exposes this to applicants |
| Submission freezing after submit | ✅ | ✅ | ✅ Parity | |
| Answer match / double-entry verification | ✅ (isAnswerMatchRequired) | ✅ | ✅ Parity | |
| Upsert on re-submission (same ID) | ✅ Jester uses ON CONFLICT DO UPDATE | ⚠️ Verify | 🔲 Validate | Confirm Terra handles re-submissions of same ID correctly |
| Silent failure prevention | ⚠️ Jester can fail silently on webhook errors | ✅ Better | ✅ Terra better | Terra has queue with retry. Verify retry logic on Airtable sync |
Airtable Sync (The Critical Path)
This is the most important section. The Zuiyo→Airtable sync is the handoff to reviewers. If this breaks, reviewers don’t see applications.| Capability | Zuiyo (current) | Terra | Status | Notes |
|---|---|---|---|---|
| Postgres → Airtable field mapping | ✅ Via struct tags or field name matching | ✅ Native integration | ✅ Parity | Mechanism differs; outcome same |
| Supported Airtable field types | singleLineText, email, url, multilineText, phoneNumber, number, currency, singleSelect, multipleSelects, date, dateTime, checkbox, multipleAttachments | ✅ Most types | 🔲 Validate | Confirm Terra maps all Zuiyo-supported types |
| Batch inserts (Airtable API limit) | ✅ 10 records/batch | ✅ | 🔲 Validate | Confirm Terra respects Airtable rate limits |
| Retry on Airtable API failure | ✅ 3 retries | ⚠️ Verify | 🔲 Validate | Confirm Terra retries failed syncs |
| Rate limiting | ✅ 8 concurrent max | ⚠️ Verify | 🔲 Validate | |
| Mapping admin UI | ✅ Zuiyo has UI for managing column→field mappings | ✅ Terra has Airtable integration config | 🔲 Validate | Confirm Terra’s mapping config is as flexible as Zuiyo’s |
| Incremental sync (only new records) | ✅ By submitted_at timestamp | ⚠️ Verify | 🔲 Validate | |
| Refresh existing records on update | ✅ ~10% refresh each sync to catch updates | ⚠️ Verify | 🔲 Validate | |
| Outcome sync: Airtable → Terra | ✅ Zuiyo reads outcome field from Airtable, writes back to Tideswell via GraphQL | ⚠️ Unclear | 🔴 Critical gap to verify | This closes the loop — reviewer approves in Airtable, applicant sees status in Terra. Does Terra receive status back from Airtable? |
| Sync history / logs | ✅ Zuiyo UI shows last 5 syncs with detailed logs | ✅ Terra has webhook event history | ✅ Parity | |
| Manual sync trigger | ✅ Via Zuiyo API | ⚠️ Verify | 🔲 Validate |
- Be configured identically to replicate current Zuiyo behavior (1:1 parity)
- Be redesigned to take advantage of Terra’s richer data model
Authentication
| Capability | Tideswell | Terra | Status | Notes |
|---|---|---|---|---|
| Applicant authentication | Firebase Identity Platform | WorkOS | 🔲 Validate | Different providers. Behavior should be equivalent but existing Firebase accounts don’t auto-migrate |
| Tenant support | ✅ Firebase tenant isolation | ✅ WorkOS orgs | ✅ Parity | |
| SSO / enterprise OAuth | ✅ Firebase | ✅ WorkOS | ✅ Parity | |
| MFA | ✅ Group-level MFA required flag | ✅ WorkOS | ✅ Parity | |
| API key auth for automation | ✅ <uuid>:<form_id> format | ✅ | ✅ Parity | |
| Anonymous / guest submissions | ✅ Groups allow unauthenticated submit | ⚠️ Verify | 🔲 Validate | Some programs allow no-account submissions |
| Existing Tideswell accounts | Firebase UIDs | N/A | 🔴 Migration needed | Applicants with existing Tideswell accounts need migration path to WorkOS if they need to log in to Terra |
File Uploads
| Capability | Tideswell | Terra | Status | Notes |
|---|---|---|---|---|
| Google Drive storage | ✅ Primary storage | ✅ Supported | ✅ Parity | |
| Supabase Storage | ❌ | ✅ | ➕ Terra extra | |
| Per-question drive folder config | ✅ driveFolderId per question | ✅ | ✅ Parity | |
| File size limit | 16 MB | Configurable | ✅ Parity | |
| MIME type restrictions | ✅ accept field | ✅ | ✅ Parity | |
| File count limits | ❌ | ✅ | ➕ Terra extra |
Notifications
| Capability | Tideswell | Terra | Status | Notes |
|---|---|---|---|---|
| Email on submission | ❌ (webhook-based only) | ✅ Resend | ➕ Terra extra | |
| SMS | ❌ | ✅ Twilio | ➕ Terra extra | |
| Plain text email | ✅ SendGrid | ✅ | ✅ Parity | |
| HTML/template email | ❌ | ✅ | ➕ Terra extra | |
| Webhook on submit | ✅ (primary mechanism) | ✅ | ✅ Parity | |
| Webhook retry (exponential backoff) | ✅ 12 attempts, ~24hr window | ✅ | 🔲 Validate | Confirm Terra’s retry behavior matches or exceeds Tideswell’s |
| Webhook event history | ✅ | ✅ | ✅ Parity |
Admin Interface
| Capability | Tideswell | Terra | Status | Notes |
|---|---|---|---|---|
| Form builder | ✅ | ✅ | ✅ Parity | |
| Drag-drop reorder | ✅ | ✅ | ✅ Parity | |
| Submission list view | ✅ | ✅ | ✅ Parity | |
| Filter submissions by status | ✅ | ✅ | ✅ Parity | |
| Update submission status | ✅ | ✅ | ✅ Parity | |
| Update outcome field (admin-set) | ✅ | ⚠️ Verify | 🔲 Validate | |
| CSV bulk import | ✅ With header-to-question mapping | ⚠️ Verify | 🔲 Validate | Check if Terra has CSV import for submissions |
| CSV export | ✅ | ✅ | ✅ Parity | |
| i18n string customization per form | ✅ | ✅ | ✅ Parity | |
| Groups / team submissions | ✅ Multiple accounts per group | ⚠️ Verify | 🔲 Validate | Tideswell supports group-scoped submissions where multiple accounts can view the same submission |
| Featured questions (submission preview) | ✅ Select which questions show in list view | ⚠️ Verify | 🔲 Validate | |
| Form scheduling (auto-publish / auto-close) | ✅ | ✅ | ✅ Parity | |
| Post-submit redirect URL | ✅ | ✅ | ✅ Parity |
Validation
| Capability | Tideswell | Terra | Status | Notes |
|---|---|---|---|---|
| Required / optional | ✅ | ✅ | ✅ Parity | |
| Min / max length | ✅ | ✅ | ✅ Parity | |
| Numeric type validation | ✅ integer, whole, currency, float | ✅ | ✅ Parity | |
| Date min / max | ✅ | ✅ | ✅ Parity | |
| Address validation (Smarty) | ✅ | ✅ | ✅ Parity | |
| Answer match (double-entry) | ✅ isAnswerMatchRequired | ✅ | ✅ Parity | |
| Age-based validation | ❌ | ✅ | ➕ Terra extra | |
| Legacy logicInRules | ✅ (some older forms) | ❌ | 🔴 Gap | Check which active forms use this pattern |
Summary: Gaps That Block v1
These must be resolved before Terra can replace Tideswell/Jester/Zuiyo for any live program:| # | Gap | Severity | Owner | Action |
|---|---|---|---|---|
| 1 | Outcome sync: Airtable → Terra | 🔴 Critical | David | Verify or build — reviewers approve in Airtable, applicants must see status in Terra |
| 2 | GroupedQuestion nesting | 🟡 High | David + May | Test: does Terra support the same nesting depth as Tideswell’s GroupedQuestion? |
| 3 | RepeatedQuestion | 🟡 High | David | Does Terra have a way to reference/reuse a question from elsewhere in the form? If not, check which forms use this |
| 4 | Legacy logicInRules | 🟡 High | Brian + May | Identify which active forms use the legacy 2D rule format — can they be rewritten as standard conditions? |
| 5 | Anonymous / guest submissions | 🟡 High | David | Confirm Terra supports unauthenticated submissions for programs that don’t require applicant accounts |
| 6 | Airtable sync retry reliability | 🟡 High | David | Confirm Terra retries failed Airtable syncs and that no submissions can silently fail to sync |
| 7 | Outcome field exposed to applicant | 🟡 High | David + May | Confirm the admin-set outcome (e.g., “Approved: $3,000”) is visible to the applicant in Terra |
| 8 | Airtable mapping config | 🟡 High | Brian + David | Decide: replicate Zuiyo mapping 1:1, or redesign? This decision gates the validation checklist |
Validation Checklist (to be completed by Brian + May)
Once the gaps above are resolved, this is the sign-off list for Terra v1 production.Form Building
- All field types used in current active programs exist in Terra
- Conditional logic on at least one complex form produces same show/hide behavior as Tideswell
- Multi-language form renders correctly in at least 2 languages
- Form scheduling (auto-publish, auto-close) works as expected
Submission Integrity
- Test submission on a real form: data lands in Terra database completely and accurately
- File upload attaches correctly to submission
- Failed submission does not silently disappear — produces visible error
- Re-submission of same ID behaves correctly (upsert, not duplicate)
Airtable Sync
- Sync a test submission: correct fields appear in correct Airtable columns
- Sync failure is logged and retried — data does not silently fail to reach Airtable
- Outcome sync: reviewer marks outcome in Airtable → applicant sees updated status in Terra
Security
- Submission is not accessible without proper authorization
- PII does not appear in error logs or Sentry
- File uploads are not publicly accessible URLs
Admin
- Submission list shows correct data for a test program
- Status can be updated on a submission
- Outcome field can be set by admin and is visible to applicant
What Terra Has That Tideswell Does Not
These are capabilities Terra ships with that can be unlocked after v1 is stable:- Field block library (reusable groups of fields across forms)
- Per-field encryption for PII
- Audit logging on all data changes
- SMS notifications (Twilio)
- Rich email templates (Resend)
- Program hierarchy (workspace → program → form)
- Form versioning and immutable submission records
- Age-based conditional logic operators
- Advanced file handling (count limits, size limits, Supabase Storage)
- Signature field
- Markdown info blocks with alert variants