Skip to content

feat(source-ashby): declare documented API fields across stream schemas - #84274

Draft
devin-ai-integration[bot] wants to merge 7 commits into
masterfrom
devin/1786495771-ashby-schema-fields
Draft

feat(source-ashby): declare documented API fields across stream schemas#84274
devin-ai-integration[bot] wants to merge 7 commits into
masterfrom
devin/1786495771-ashby-schema-fields

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

What

Requested by Patrick Nilan (@pnilan) via /ai-fix on airbytehq/airbyte-internal-issues#16922 (audit finding S-1: 49 documented Ashby API fields undeclared across 10 stream schemas).

source-ashby declares its stream schemas inline in manifest.yaml. Comparing them against Ashby's published OpenAPI definitions showed a large set of documented top-level fields that were never declared, plus many objects/arrays declared as bare type: object / type: array with no properties/items. Since every stream sets additionalProperties: true those fields still pass through at runtime, but they are absent from the catalog — untyped, not selectable in the UI, and not guaranteed in destinations.

Field lists were re-derived independently of the audit, from the machine-readable OpenAPI blocks Ashby publishes on each reference page (e.g. https://developers.ashbyhq.com/reference/userlist.md), rather than taken from the issue text. That re-derivation matched the audit and also surfaced four fields the audit missed on interview_schedules (createdAt, updatedAt, scheduledBy, interviewEvents) and five extra on jobs (createdAt, updatedAt, openedAt, closedAt, brandId, which the audit flagged for verification).

How

Declared the documented-but-missing top-level fields on 12 streams:

Stream Added
applications openings
candidates location
custom_fields description, isPrivate, isRequired, selectableValues
departments createdAt, externalName, extraData, updatedAt
interview_schedules createdAt, updatedAt, scheduledBy, interviewEvents
interview_stages interviewStageGroupId
jobs author, brandId, closedAt, compensation, createdAt, location, openedAt, openings, updatedAt
job_postings applicationDeadline, applyLink, compensationTierSummary, shouldDisplayCompensationOnJobBoard, status, updatedAt, workplaceType
locations externalName, extraData, parentLocationId, type, workplaceType
offers formDefinition, offerStatus, versions
users customFields, globalRole, isEnabled, managerId, updatedAt
application_criteria_evaluations id, criterion, status, skipReason, outcomeNumber, evaluatedAt

Everything added is nullable (type: ["null", <type>]) to match the existing convention, with format: date-time/format: date where documented.

Previously-bare nested objects/arrays were expanded one level: their documented child properties are declared with scalar types, and any grandchild object/array stays bare. This is a deliberate bound to keep the change reviewable — e.g. candidates.emailAddresses.items now declares value/type/isPrimary, but offers.latestVersion.salary stays a bare object.

Polymorphic fields are declared as the full documented union rather than one branch: customFields[].value is ["null", "boolean", "number", "string", "array", "object"] and customFields[].valueLabel is ["null", "string", "array"] (Ashby documents both as oneOf). Declaring one branch would have been worse than leaving them undeclared.

Deliberately not changed

  • interviews — untouched. Its declared schema and the documented interview.list object share only id; the declared shape (applicationId, interviewScheduleId, startTime, meetingLink, …) looks like a scheduled-interview object, not an interview definition. Either the schema was derived from a different resource or the docs and live response have diverged. Adding the 11 documented fields here without a live response to check against would likely produce 11 permanently-null columns. Needs live verification first.
  • No declared field was removed, including undocumented ones (interview_stages.isArchived, application_criteria_evaluations.assessmentType/criterionName/jobId) — they presumably came from real responses.
  • No primary_key changed. application_criteria_evaluations still has primary_key: [] even though id is now declared; setting a PK is a separate change with different blast radius.

Review guide

  1. airbyte-integrations/connectors/source-ashby/manifest.yaml — the schema additions. Note some existing properties moved: new fields were inserted alphabetically, which reordered a handful of neighbours.
  2. metadata.yaml + docs/integrations/sources/ashby.md — version bump and changelog.

Test Coverage

No tests. A unit test module pinning the declared schemas to the documented field lists was added initially and removed at Patrick Nilan (@pnilan)'s request — it only restated the diff rather than covering behavior.

No live Ashby credentials exist for this connector (nothing in GSM for source-ashby, nothing in 1Password), so the fields could not be confirmed against a live response either. This is a schema-vs-published-OpenAPI reconciliation only.

Declarative-First Evaluation

No custom Python component was added or needed — this is a pure InlineSchemaLoader manifest change.

Breaking Change Evaluation

Not breaking. No field was removed or retyped, no primary key, cursor, spec, or state format changed, and no stream stops returning records. Adding declarations to a schema whose additionalProperties is already true only surfaces fields that were already flowing through. Bumped 0.3.80.4.0 (minor: catalog additions). Progressive rollout is disabled for this connector, so no -rc suffix.

User Impact

Newly-declared fields become typed, selectable in the UI, and guaranteed in destinations. Users need to refresh the source schema to pick them up. metadata.autoImportSchema is false on all streams, so this won't happen automatically.

Follow-ups (not in this PR)

  • Verify interviews against a live interview.list response and reconcile the declared shape.
  • Consider primary_key: [id] for application_criteria_evaluations.
  • Consider enabling autoImportSchema on streams where it's appropriate, so drift like this self-corrects.

Can this PR be safely reverted and rolled back?

  • YES 💚
  • NO ❌

Related to https://github.com/airbytehq/airbyte-internal-issues/issues/16922:


Devin session

devin-ai-integration Bot and others added 4 commits August 12, 2026 00:52
Co-Authored-By: bot_apk <apk@cognition.ai>
Co-Authored-By: bot_apk <apk@cognition.ai>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@github-actions

Copy link
Copy Markdown
Contributor

👋 Greetings, Airbyte Team Member!

Here are some helpful tips and reminders for your convenience.

💡 Show Tips and Tricks

PR Slash Commands

Airbyte Maintainers (that's you!) can execute the following slash commands on your PR:

  • 🛠️ Quick Fixes
    • /format-fix - Fixes most formatting issues.
    • /bump-version - Bumps connector versions, scraping changelog description from the PR title.
      • Bump types: patch (default), minor, major, major_rc, rc, promote.
      • The rc type is a smart default: applies minor_rc if stable, or bumps the RC number if already RC.
      • The promote type strips the RC suffix to finalize a release.
      • Example: /bump-version type=rc or /bump-version type=minor
    • /bump-progressive-rollout-version - Alias for /bump-version type=rc. Bumps with an RC suffix and enables progressive rollout.
  • ❇️ AI Testing and Review (internal link: AI-SDLC Docs):
    • /ai-prove-fix - Runs prerelease readiness checks, including testing against customer connections.
    • /ai-canary-prerelease - Rolls out prerelease to 5-10 connections for canary testing.
    • /ai-review - AI-powered PR review for connector safety and quality gates.
  • 📝 AI Documentation:
    • /ai-docs-review - AI-powered documentation review for PRs with connector changes.
    • /ai-create-docs-pr - Creates a documentation PR for connector changes, stacked on the current PR.
  • 🚀 Connector Releases:
    • /publish-connectors-prerelease - Publishes pre-release connector builds (tagged as {version}-preview.{git-sha}) for all modified connectors in the PR.
    • /enable-autopilot-rollouts - Enables autopilot progressive rollouts for the modified connector(s) in the PR, remediating "autopilot rollouts not enabled for {connector-name}" auto-merge blockers. Sets defaultRolloutMode: autopilot and enableProgressiveRollout: true, preserving any existing autopilotConfig.
      • Optional args: connector=<CONNECTOR_NAME> (defaults to the modified connectors in the PR), strategy=fast|slow|default (defaults to fast).
      • Example: /enable-autopilot-rollouts or /enable-autopilot-rollouts connector=source-faker strategy=slow
  • ☕️ JVM connectors:
    • /update-connector-cdk-version connector=<CONNECTOR_NAME> - Updates the specified connector to the latest CDK version.
      Example: /update-connector-cdk-version connector=destination-bigquery
  • 🐍 Python connectors:
    • /poe connector source-example lock - Run the Poe lock task on the source-example connector, committing the results back to the branch.
    • /poe source example lock - Alias for /poe connector source-example lock.
    • /poe source example use-cdk-branch my/branch - Pin the source-example CDK reference to the branch name specified.
    • /poe source example use-cdk-latest - Update the source-example CDK dependency to the latest available version.
  • ⚙️ Admin commands:
    • /force-merge reason="<REASON>" - Force merges the PR using admin privileges, bypassing CI checks. Requires a reason.
      Example: /force-merge reason="CI is flaky, tests pass locally"
📚 Show Repo Guidance

Helpful Resources

📝 Edit this welcome message.

Co-Authored-By: bot_apk <apk@cognition.ai>
@github-actions

Copy link
Copy Markdown
Contributor

Note

Autopilot progressive rollouts are not enabled for the following modified connector(s):

  • source-ashby

This is a courtesy heads-up only — it does not block merge or fail any check.
To enable automatic progressive rollouts for the connector(s) above, comment
/enable-autopilot-rollouts on this PR. This sets defaultRolloutMode: autopilot
and enableProgressiveRollout: true in each connector's metadata.yaml,
preserving any existing autopilotConfig.

@github-actions

github-actions Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

source-ashby Connector Test Results

3 tests   1 ✅  3s ⏱️
1 suites  2 💤
1 files    0 ❌

Results for commit 432eca5.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Deploy preview for airbyte-docs ready!

Project:airbyte-docs
Status: ✅  Deploy successful!
Preview URL:https://airbyte-docs-3crh3x3t2-airbyte-growth.vercel.app
Latest Commit:432eca5

Deployed with vercel-action

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

remove these tests, unneeded

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

👍 On it. Removing the whole unit_tests/ directory — they only assert that the manifest's declared properties match a hardcoded field list, which is a restatement of the diff rather than a behavioral test. Will push shortly and leave the manifest/metadata/changelog changes as-is.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

☑️ Resolved in f58469f. unit_tests/ removed; PR description updated so it no longer claims test coverage.

Co-Authored-By: bot_apk <apk@cognition.ai>
@airbyte-support-bot

Copy link
Copy Markdown
Contributor

↪️ Triggering /ai-prove-fix per Hands-Free AI Triage Project triage next step.

Reason: Draft schema fix with CI green (only Progressive Rollout Gate checks were cancelled); prove-fix validation is the next pipeline step for:

https://github.com/airbytehq/oncall/issues/13283

Devin session

@octavia-bot

octavia-bot Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

🔍 AI Prove Fix session starting... Running readiness checks and testing against customer connections. View playbook

Devin AI session created successfully!

@airbyte-support-bot

Airbyte Support Bot (airbyte-support-bot) commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

✅ Fix Proven — /ai-prove-fix

The 0.4.0 schema additions land in the discovered catalog exactly as intended, and no data regression was found. Safe to merge.

Evidence in one line: against a live source, DISCOVER on 0.4.0 declares the new fields across 13 streams — every difference is an addition (no removals, no retypes, no narrowing) — while SPEC, CHECK, record counts, primary keys and final state are all identical to 0.3.8.

Two ❌ rows appear in the regression report and both are explained, neither is a regression — see Detailed evidence below:

  1. DISCOVER catalog_schema is marked strict rather than ⚠️-additive because the PR expands previously bare objects/arrays one level, which the harness classifies as re-declaration rather than growth. The diff itself is purely additive.
  2. READ flags candidates on the school field — reproduced with identical connector code on both sides, so it is pre-existing upstream non-determinism, not this PR.
Next steps
  • Merge, then run /ai-canary-prerelease to watch the first organic syncs.
  • Consider calling out in the changelog that existing users must refresh the source schema to pick up the new fields (autoImportSchema: false for this connector) — the fields already arrive in the data, but the catalog won't grow on its own.
  • Separately from this PR: record comparison for source-ashby will red-flag candidates on every comparison run until school is excluded, because the API returns it non-deterministically between the two sequential reads.
  • Daily hands-free triage will monitor the rollout after merge.
Connector & PR details
  • Connector: source-ashby (source, manifest-only / declarative), airbyte/source-ashby
  • Version: 0.3.80.4.0; pre-release published as airbyte/source-ashby:0.4.0-preview.f58469f (publish run)
  • Change: inline stream schemas in manifest.yaml only, plus metadata.yaml version and the docs changelog. No components, requesters, extractors or transformations touched.
  • Streams gaining declarations (13): application_criteria_evaluations, applications, candidates, custom_fields, departments, feedback_form_definitions, interview_schedules, interview_stages, job_postings, jobs, locations, offers, users
  • Streams unchanged (4): archive_reasons, candidate_tags, interviews, sourcesinterviews unchanged in the discovered catalog confirms the PR's deliberate deferral of that stream.
  • Base image: airbyte/source-declarative-manifest:7.17.4 (unchanged by this PR)
Evidence plan

Proving criteriaDISCOVER on the target declares the new fields on the listed streams, absent from the control catalog, with no removal/retype; and READ shows no record-count decrease, no dropped primary keys, no state-shape change vs control.

Disproving criteria — a non-additive catalog change, an incompatible SPEC change, fewer records, missing PKs, or mutated field values attributable to the connector.

Comparison baselinelatest = 0.3.8. No known-bad version is named in the PR or the audit issue: this is a documented-vs-declared reconciliation, not a version regression, so latest is the "before" state. No major-version boundary crossed.

Strategy — regression tests only, in comparison mode. The observable change lives entirely in the discovered catalog, which the harness compares directly, so no live pinning or customer sync was warranted. No connection was pinned, no sync triggered, no version override set.

Pre-flight checks — all pass
  • Viability ✅ — resolved and diffed both manifests structurally: 125 property declarations added across 12 streams, 0 removed, 0 retyped. The declarations match the fields the audit found undeclared, so the change does address the reported issue.
  • Safety ✅ — no executable code added (manifest-only, InlineSchemaLoader); no auth, credential, or network behavior touched; nothing obfuscated.
  • Breaking change ✅ not breaking — no field removed or retyped, no primary-key change, no cursor change, no spec change, no stream removed, no data-scope narrowing, no state-format change. 0.3.8 → 0.4.0 is the right bump for additive catalog growth. (enableProgressiveRollout: false is pre-existing in metadata.yaml and was not weakened by this PR.)
  • Reversibility ✅ — rolling back to 0.3.8 simply restores the narrower catalog; no config or state written by 0.4.0 becomes unreadable, and the changelog entry is present.
  • Design intent ✅ — the added fields already flow through at runtime because every stream keeps additionalProperties: true, so this declares existing behavior rather than reversing an intentional decision.
Detailed evidence

Four regression runs; one was infrastructure-only and does not count as a verdict.

# Setup Outcome
1 GSM secrets, all streams, comparison mode — run ⚙️ Infrastructure failure, not a verdict. CHECK aborted with Failed to fetch integration test config from GSM for source-ashbyValueError: Config is required for check command. source-ashby has no GSM integration-test secret, so the GSM path cannot test this connector at all.
2 Live connection (Connection A — TIER_2, non-EU, unpinned), 10 selected streams, warm read — run SPEC ✅ · CHECK ✅ · DISCOVER ❌ (13 streams changed, additive_only=false) · READ ❌ (candidates, 85 records, school only)
3 Same connection, repeat run — run Same shape, but candidates value diffs 14 records — again school only. An identical setup producing 85 then 14 is the first signal that school is run-to-run noise.
4 Discriminating run: identical connector code on both sides (control overridden to the 0.4.0 pre-release) — run DISCOVERDiscovered catalog unchanged across 17 streams · READcandidates 94 records still differ, school only

Finding 1 — the catalog change is exactly the intended additive declaration. In the attempt-2 DISCOVER diff, all 13 changed streams report only dictionary_item_added — zero dictionary_item_removed, zero type_changes, zero values_changed. The check still renders ❌ because additive_only is a whole-check verdict and this PR adds properties / items to fields that already existed (candidatecandidate.properties, hiringTeamhiringTeam.items), which the harness scores as re-declaration rather than growth. Since every stream keeps additionalProperties: true and no additionalProperties: false is introduced, declaring subfields cannot drop data.

Finding 2 — the candidates READ failure is not this PR. Attempt 4 ran the same build against itself and still reported 94 differing candidates records, exclusively on root['data']['school']. Across three live runs the count was 85 → 14 → 94, and no other field ever appeared. A schema-only PR has no code path that could rewrite a field value, so the difference comes from the API returning school non-deterministically between the sequential control and target reads.

Everything else clean, on every live run:

  • SPEC ✅ — no spec change; no saved config becomes invalid.
  • CHECK ✅ — both versions connect.
  • Record counts identical target vs control on all 8 read streams (largest: applications 21,905 and candidates 20,747) — no decrease anywhere, and records_only_in_control = 0.
  • pk_presence ✅ (0 missing, 0 extra), pk_uniqueness ✅ on both control and target.
  • Final state ✅ Final state unchanged across 10 streams.
  • The fix was exercised, not merely un-regressed: the new declarations appear on 13 streams in DISCOVER, and the read covered 10 of them against live data.

Customer-identifying details for the connection used are recorded privately in the originating internal issue and deliberately omitted here.


Devin session

@airbyte-support-bot Airbyte Support Bot (airbyte-support-bot) added the hyd-prove Hydra: ai-prove-fix stage has run label Aug 12, 2026
@github-actions

github-actions Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Pre-release Connector Publish Started

Publishing pre-release build for connector source-ashby.
PR: #84274

Pre-release versions will be tagged as {version}-preview.f58469f
and are available for version pinning via the scoped_configuration API.

View workflow run
Pre-release Publish: SUCCESS

Docker image (pre-release):
airbyte/source-ashby:0.4.0-preview.f58469f

Docker Hub: https://hub.docker.com/layers/airbyte/source-ashby/0.4.0-preview.f58469f

Registry JSON:

Co-Authored-By: bot_apk <apk@cognition.ai>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

connectors/source/ashby hyd-fix Hydra: ai-fix stage has run hyd-prove Hydra: ai-prove-fix stage has run

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants