Org Web Adapter

hungryroot/goals/hungryroot-2026-q2-goals-draft.org

ID
3392fa99-0fc4-440a-a157-60a6e00c6a3c

Hungryroot 2026 Q2 Goals Draft

# Q2 2026 — API/Backend goals

Status: draft. Owner: Colin Powell. Quarter: Q2 2026 (Apr–Jun). Authored 2026-05-18.

## Summary

Support Brand Pod Q2 execution by hardening the API platform that brand and growth surfaces depend on — reducing integration friction, accelerating cross-team release velocity, and making Brand a first-class entity in the backend. This includes:

- **Consolidating the API surface** by completing the V1 → V2 transition so client teams build against one consistent, documented contract.

- **Unblocking mobile delivery** through standing visibility into iOS/Android endpoint dependencies, named owners on both sides, and a minimum-supported-version policy that retires long-tail clients.

- **Preventing cross-team integration defects** by introducing automated contract testing (Schemathesis for schema accuracy, Pact for consumer-driven contracts and a `can-i-deploy` release gate).

- **Elevating Brand to a first-class backend concept** with a canonical `Brand` model, image and metadata, and a migration path off the denormalized `Product.brand_name` string.

Success means delivering an API platform where brand and growth surfaces ship faster, with fewer mobile integration regressions, against a documented contract — and where Brand-driven product experiences (logos, descriptions, brand-filtered discovery) are supported natively rather than bolted onto a free-text field.

### Workstreams

1. Finish V1 → V2 traffic transition.

2. Follow up with iOS/Android on remaining endpoints.

3. Stand up automated API contract testing (Schemathesis + Pact, two-phase).

4. Make Brand a first-class concept in the backend.

Workstreams 1, 2, and 3 are coupled: contract tests reduce migration risk; mobile sync unblocks deprecations. Workstream 4 is independent but benefits from the contract harness for new endpoints.

---

## 1. Finish V1 → V2 traffic transition

**Why now:** v2 noslash variants just removed (BE-7208 #14018). Migration entering tail end — long-tail clients are the remaining risk.

**Workstreams**

- **Datadog traffic audit** — query `/api/v1/*` hits over rolling 7d. Bucket by route + client (`User-Agent`, app version). Identify which v1 endpoints still see non-zero traffic.

- **Per-route migration tickets** — one BE ticket per remaining v1 route with traffic. Each: confirm v2 equivalent exists, file client migration ask, set deprecation date.

- **Deprecation header rollout** — return `Deprecation` + `Sunset` headers on remaining v1 routes so clients surface in logs/Sentry.

- **Kill-switch dry-run** — for routes <X req/day, gate behind dynamic-config flag; flip in staging, confirm no breakage, schedule prod flip.

- **Close out BE-7208** — already in *Testing in Progress*. Finish remaining trailing-slash audit work.

**Success criteria**

- v1 traffic <1% of total API requests (or named exempt list).

- Every remaining v1 route has either: (a) sunset date in client backlog, or (b) documented exemption.

- Deprecation headers live on all v1 routes.

**Risks**

- Long-tail client versions never auto-update — need product alignment on minimum-supported-version bump.

---

## 2. iOS/Android endpoint followups

**Why now:** Mobile owns the slowest-moving client. Need standing visibility, not ad-hoc asks.

**Workstreams**

- **Mobile endpoint matrix** — Confluence/Notion page listing every endpoint mobile calls, current version (v1/v2/v3), latest app version using it. Source: Datadog `app.version` tag breakdown.

- **Sync cadence** — biweekly 30-min with iOS + Android leads. Agenda: what's left, what's blocking, what they need from BE.

- **Per-platform migration tickets** — file under shared epic. Mobile owns app-side; BE owns endpoint readiness + parity testing.

- **Minimum-version policy** — propose with mobile + product: after N months, force-upgrade clients on retired v1 routes.

**Success criteria**

- Matrix exists + refreshed monthly.

- Every mobile-called v1 route has named owner on both sides + target date.

- Force-upgrade policy documented + first enforcement date set.

**Risks**

- App-store review cycles add weeks. Bake into target dates.

- iOS/Android may not have eng capacity — need EM-level commitment.

---

## 3. Automated API contract testing — Schemathesis + Pact (two-phase)

**Why now:** Proposal already drafted ([Backend Project Proposal: Contract Testing with Schemathesis and Pact](https://hungryroot.atlassian.net/wiki/spaces/BA/pages/1535868929/)). Phase 1 timeline starts 5/4 — already in flight as of 5/18. Phase 2 spills into Q3 (ends 7/26). Treat Phase 1 closeout as Q2 commit; Phase 2 = Q2 kickoff + Q3 finish.

### Phase 1 — Schemathesis (Q2 commit, 5/4 – 5/31)

Harden the OpenAPI schema as the single source of truth for client integrations by validating it against actual backend behavior in CI. This includes:

- **Closing the gap between documented and implemented contracts** by running property-based tests over the `drf-spectacular` schema and surfacing every request/response mismatch.

- **Raising the quality of generated schema annotations** so downstream consumers (mobile codegen, Phase 2 Pact contracts, future SDKs) inherit accurate types instead of best-guess shapes.

- **Establishing a required CI gate** for schema drift, so annotation gaps and breaking changes are caught at PR time rather than at integration.

- **Documenting the harness** so any backend engineer can run, extend, and triage contract failures without specialist knowledge.

Success means the top 20 endpoints by mobile traffic are covered by property-based contract validation, schema/implementation mismatches stop escaping to staging, and Phase 2 (Pact) starts from a trustworthy schema foundation rather than papering over drift.

**Objective:** Validate OpenAPI schema against actual request/response behavior. Catch drift in CI.

**Workstreams**

- Add `schemathesis` to `requirements-test.txt`.

- Scaffold `app/tests/rest/contract/` — property-based tests load `drf-spectacular` schema, run via Django test client (no live server needed).

- Factory Boy auth fixtures for protected endpoints.

- Triage + fix `drf-spectacular` annotation gaps revealed by Schemathesis.

- New `contract-tests` job in `.github/workflows/django-tests.yml` — required check.

- Runbook: how to run locally, how to triage failures.

**Coverage target**

- Top 20 endpoints by mobile traffic / error budget. Auth (login/refresh/logout), user profile, highest-traffic domain reads.

**Success criteria (per proposal)**

- ≥90% of top 20 endpoints validated by Schemathesis.

- Zero schema/implementation mismatches escape to staging post-Phase 1.

- CI stage green + required.

**Risks**

- Schema annotation gaps wider than estimated → extends Phase 1.

- *Mitigation:* daily triage, parallelize fixes, prioritize by traffic.

**Owner:** [unassigned]

### Phase 2 — Pact (Q2 kickoff 6/1, finish Q3 by 7/26)

**Objective:** Consumer-driven contracts with iOS + Android. `can-i-deploy` gate blocks incompatible releases.

**Workstreams**

- Cross-team kickoff (target 6/3): ownership, versioning, contract-freeze rules.

- Stand up PactFlow free tier broker.

- iOS + Android each author top 10 consumer pacts, publish on release branches.

- BE adds `pact-python`, provider-verification job in CI.

- Broker webhook → triggers provider verification on new consumer pact publication.

- Release pipeline step calls `can-i-deploy`; blocks incompatible deploys.

- Runbooks: pact authorship, verification failures, versioning.

**Success criteria (per proposal)**

- PactFlow live, automated verification green.

- 100% releases guarded by `can-i-deploy`.

- ≥50% reduction in mobile-backend integration defects within 2 release cycles.

**Risks**

- Cross-team coordination overhead — needs Android + iOS lead commitment.

- *Mitigation:* kickoff training, examples repo, clear SLAs.

- Test-data nondeterminism breaks provider verification.

- *Mitigation:* seeded factories, stable provider states.

**Owners:** Backend lead (verification + gate), Android lead (consumer pacts), iOS lead (consumer pacts).

### Coupling to other Q2 goals

- **Couples to goal 2:** Phase 2 kickoff = the forcing function for the biweekly iOS/Android cadence. Bring contract testing onto that agenda.

- **Couples to goal 1:** Schemathesis only runs against documented endpoints. v1 routes outside `drf-spectacular` won't get coverage — another reason to retire them.

- **Couples to goal 4:** new Brand endpoints land *after* Phase 1 — they should be born with accurate schema annotations + included in contract coverage.

### Immediate next actions (this week)

- [ ] Assign Phase 1 owner.

- [ ] Add `schemathesis` to `requirements-test.txt`, scaffold `app/tests/rest/contract/`.

- [ ] Open PR with `contract-tests` CI job (non-blocking initially).

- [ ] Schedule 6/3 cross-team Pact kickoff.

---

## 4. Brand as first-party backend concept

Elevate Brand from a denormalized text field on Product to a canonical entity that the rest of the platform — discovery, search, merchandising, and client surfaces — can build against. This includes:

- **Establishing canonical brand identity** with a stable `Brand` model carrying slug, display name, marketing copy, and visual assets, replacing inconsistent `Product.brand_name` strings.

- **Enabling brand-driven product experiences** through a Product ↔ Brand relationship that supports brand-filtered discovery, brand pages, and brand-aware search ranking.

- **Preserving search and discovery quality** by indexing canonical brand data in Algolia/OpenSearch with read-fallback to the legacy field during transition.

- **Giving ops a real management surface** for brand metadata (logos, descriptions, activation state) instead of free-text edits per product.

Success means brand and growth teams can launch brand-led merchandising and discovery experiences against a real model — with consistent spelling, shared assets, and clean cardinality — without requiring a one-off integration per surface.

**Why now:** Plan doc already drafted ([`docs/brand/first-class-brand-model-plan.md`](./brand/first-class-brand-model-plan.md)). Q2 = land Phase 1, scope Phase 2.

### Phase 1 — Model + admin (Q2 commit)

- `Brand` model: `name`, `slug`, `description`, `image`, `is_active`, `sort_order`.

- `ProductBrand` through model with `is_primary`.

- Migration + backfill management command from distinct `Product.brand_name` values.

- `BrandAdmin` + `ProductAdmin` autocomplete.

- Read-only API endpoints (list/detail by id + slug).

- Algolia/OpenSearch: index `brand.name` alongside existing `brand_name`.

### Phase 2 — Product integration (Q2 stretch / Q3)

- Product serializers embed `brands` minimal payload.

- `brand` / `brands` filter on `ProductFilter`.

- Read-path switch: prefer `Brand.name`, fall back to `brand_name`.

### Phase 3 — Deprecation (Q3+)

- Stop writes to `brand_name`. Field removal after adoption metrics.

### Open questions (resolve early Q2)

- Product confirms cardinality: M2M vs FK? Plan assumes M2M; FK is simpler.

- Image storage: reuse `Product` image conventions or new abstraction?

- Client surface for v3 product responses — coordinate with goal 1.

### Success criteria

- Phase 1 shipped to prod, backfill run, admin in use by ops.

- Phase 2 scoped + first endpoint integration merged.

- No client deprecation of `brand_name` yet (Q3).

### Risks

- Backfill normalization (slug collisions, misspellings) — needs ops review queue.

- Algolia reindex cost / timing — coordinate with search team.

---

## Cross-cutting

- **Tracking:** epic per goal, weekly status in pod sync.

- **Capacity check:** 4 goals in ~6 remaining weeks is ambitious. Recommend Brand Phase 1 + contract Phase 1 as must-land; V1→V2 + mobile sync as continuous progress, not 100% complete.