# Everee White-Label Payroll Integration — Architecture & Decisions

**Original analysis**: 2026-05-08 (system surface mapping)
**Decisions session**: 2026-05-18 (architectural decisions locked)
**Status**: Architecture locked. Ready to draft Phase 0 + Phase 1a PRD.
**Scope**: White-label Everee payroll inside BK web admin, Live (manager) Flutter app, and Team (employee) Flutter app — for existing BuyerKiosk resale clothing store customers.

---

## Executive Summary

Everee is a fit. They are an **embedded-payroll provider** explicitly targeting vertical SaaS embedders, with seven drop-in UI components (iframe + Flutter `webview_flutter` wrappers), a REST API at `https://api.everee.com`, full white-label branding (admin portal + emails + sign-in), and **they own tax filing, tax remittance, and money movement (ACH + instant pay + pay card) in all 50 states**. The store remains the employer of record (non-PEO) with its own EIN.

**Target framing (locked 2026-05-18)**: This is a **feature add for existing BuyerKiosk resale clothing store customers**, NOT a general payroll SaaS competing with Gusto/ADP/Square. Several scope simplifications follow from this (no tips, no 1099s, no restaurant/salon verticals).

**The opportunity**: BuyerKiosk becomes a one-bill platform — POS + scheduling + payroll — with a structural moat that schedule-only competitors (WhenIWork, Homebase) cannot match. Everee handles the regulated parts (taxes, money, banking, IRS); we handle integration and presentation.

**The lift**: ~15-21 weeks (4-5 months) to first pilot for a focused engineer-led team with AI assistance. ~40% of the data infrastructure already exists (timesheets, approval workflow, multi-store users, jurisdiction-aware overtime calculator, immutable audit trails). The remaining 60% is mostly: employee-payroll-profile fields, per-position pay-rate storage with effective dating, BK-owned PTO accrual engine, Everee API client, webhook receiver, embed-component hosting in both Flutter apps, payroll-run review UI in the Live app, employee earnings UI in the Team app, QBO journal-entry auto-generation, and a daily reconciliation job.

**Critical caveat**: Several specifics are partner-gated (sandbox URL, exact pricing, self-serve provisioning, bulk W-2 retrieval API, full webhook enumeration, co-branded support availability). Listed in §13 as items to confirm with Everee partner team. Most are no longer blocking architecture but block implementation start.

---

## Target Market & Positioning (added 2026-05-18)

We are NOT selling this as general payroll to anyone. This is for existing BuyerKiosk resale clothing store customers.

**Implications:**
- No need to compete with Gusto/ADP/Square on positioning. The pitch is "your same BK login, your same workers, now their paychecks too."
- Onboarding scale is bounded by existing customer count, not unlimited growth. **White-glove launch is viable** for the first batch.
- Vertical edge cases vanish: no tips (resale doesn't tip), no trade-credit comp (rare in resale), no 1099 contractors (not used), no salon/restaurant/construction quirks.
- Pricing markup can be modest — we're capturing more wallet from existing customers, not stealing share.
- Existing customer payroll provider mix is concentrated in **ADP/Paychex, QuickBooks Payroll, and Homebase** — drives migration-tooling priority order (see §11).

---

## 1. Responsibility Split (Everee vs. BuyerKiosk)

### Everee owns
- Worker onboarding mechanics (W-4, I-9, W-9, direct deposit setup) — via `ONBOARDING` embed component
- Federal / state / local tax calculation (gross-to-net)
- Tax filing + remittance (quarterly + annual, all 50 states)
- W-2 / 1099 generation + distribution
- Money movement: same-day ACH, instant pay, Everee Visa Pay Card
- Banking partner relationships, ACH origination
- Pay stub generation (PDF + storage)
- Compliance updates (tax law changes, new state rules)
- Hosted white-label admin portal (branded with our logo/colors/emails)
- **Tier-1 support for paycheck questions** (decided 2026-05-18) — every BK payroll screen visibly directs merchants to Everee for paycheck disputes

### BuyerKiosk owns
- Tenant provisioning (creating a Company Instance per EIN, NOT per store — see EIN mapping below)
- Per-tenant API token storage (encrypted)
- Employee identity mapping (our `users.id` ↔ Everee `worker_id`)
- Hours/timesheet push from `scheduleTimesheets` to Everee
- Per-position pay rate storage and enforcement, effective-dated
- **PTO/sick/vacation accrual engine** (decided 2026-05-18) — balances, request flow, manager approval. Hours pushed to Everee at pay time as PTO pay code.
- Pay-run lifecycle UI (create → preview → owner approves in BK → deep-link to Everee for final commit) for managers
- Webhook ingestion (11 events) and our local state updates
- Embed component hosting in Web, Live app, Team app
- Permissions (who can run payroll, who can see earnings)
- Audit trail for sensitive actions (rate changes, terminations)
- Onboarding-kickoff trigger from our app to Everee
- **QBO journal-entry auto-generation** (decided 2026-05-18, Phase 1) — every approved pay run posts a JE with COA-mapped wage expense per position. Everee has no GL export; this is our moat.
- **Tier-1 support for app questions only** (decided 2026-05-18) — escalate paycheck issues to Everee with clear in-app guidance.
- **Customer offboarding** — full data export + Everee company handoff to direct-billing relationship. Build into MVP, not afterthought.

### Locked branding/support decisions (2026-05-18)
- **Branding**: Full white-label. Worker sees "BuyerKiosk Payroll" (or unbranded), not "Powered by Everee".
- **Support tier**: Everee handles all paycheck questions, BK handles app. Ask partner manager whether co-branded support is available (their reps answering as us).
- **Pricing model**: We pay Everee, charge merchant a single bundled subscription. We carry float on Everee fees. True white-label including billing.

---

## 2. What BuyerKiosk Already Has & Critical Gaps

### Solid foundations
| Surface | Status | Reference |
|---|---|---|
| Time punch model with break tracking | Built | `userfrosting/src/BuyerKiosk/Scheduling/Models/TimePunch.php` |
| Timesheet aggregation (regular/OT/doubletime) | Built | `userfrosting/src/BuyerKiosk/Scheduling/Models/Timesheet.php` |
| Manager approval workflow (`pending → approved → exported`) | Built | Timesheet model, status field |
| **Jurisdiction-aware overtime calculator** (US-FLSA, California daily/weekly/7th day, Canadian provinces) | Built | `userfrosting/src/BuyerKiosk/Scheduling/Services/OvertimeCalculator.php` |
| Multi-store user assignment | Built | `userStoreAssignments` (typeNum-scoped) |
| Generic CSV timesheet export | Built | `TimesheetExporter.php` |
| Immutable audit trails (shifts + punches with old/new JSON snapshots) | Built | `scheduleAuditLog`, `scheduleShiftAudit`, `schedulePunchAudit` |
| Email infrastructure (SendGrid) | Built | Mailer + Twig templates |
| QuickBooks Online integration (GL only, not payroll) | Built | `userfrosting/src/BuyerKiosk/QuickBooks/` |
| Permissions framework (Owner/Manager/ShiftLead/Buyer/Cashier) | Built | `RoleConfigService.php` |
| Ably real-time event publishing infrastructure | Built | `Core/AblyPublishThrottle.php` — ready to reuse for payroll events |
| Person-centric user accounts (unique emails/usernames already; userStoreAssignments links them) | Mostly built | Verify cross-merchant case before Phase 0 commit |

### Critical gaps (must add)
| Gap | Why it matters | Severity | Status |
|---|---|---|---|
| Legal name (`firstName`/`lastName` split from display name) | Tax filing requires legal name | High | Required |
| DOB, full address, phone (separate field) | Required on W-4 | High | Required |
| SSN / TIN tracking | Onboarding identity verification (Everee collects; we track verification status) | High | Required |
| Work authorization status | I-9 compliance (Everee collects; we mirror status) | Medium | Required |
| **Per-position pay rate storage with effective dating** | We have a single `hourlyRate` field on Employee; need per-employee+per-position with `effective_from`/`effective_to` | **Critical** | Required |
| Salaried vs. hourly distinction | Different payroll handling — confirmed in MVP scope | Medium | Required |
| Tip tracking | Never used (resale doesn't tip) — but add nullable columns in Phase 0 to avoid future migration | Deferred | Phase 0 columns only |
| Bonus / off-cycle pay flow | Off-cycle pay run, retro pay, termination final paycheck | Medium | MVP scope |
| Store legal entity (EIN, legal name, registered address) | Per-tenant Everee Company Instance | **Critical** | Required |
| 1099 vs W-2 distinction | Not in MVP scope (resale doesn't use 1099s) | N/A | Phase 2 |
| **BK-owned PTO accrual engine** | Decided 2026-05-18: BK owns accrual, balances, request flow. Pushed to Everee as PTO pay code at pay time. | High | Required |
| Employee earnings view (Team app) | Self-service expectation | High | Required |
| Pay-run UI (Live app) | Manager workflow | Critical | Required |
| ACH / banking integration | None today | N/A | Everee owns this |
| Pay stub PDF generation | None today | N/A | Everee owns; we display |
| **Two parallel `Employee` classes (`Core\Employee` + `Employee\Employee`)** | Payroll touches both; cannot afford ambiguity in this domain | Phase 0 blocker | Reconcile before any payroll code |

---

## 3. Locked Architectural Decisions (2026-05-18)

Single section listing every decision made in the 2026-05-18 brainstorming session, so future contributors have one place to look.

### Data ownership (split source of truth)
- **BK owns**: name, work email, hire/term dates, position+store assignments, pay rate (mirrored to Everee)
- **Everee owns**: legal name (canonical), SSN, home address, DOB, W-4, I-9, bank info, tax forms
- **SSN and bank info NEVER enter BK's database** — embedded Everee components render these flows inside our UI shell. Big compliance win (SOC 2 scope stays small).

### EIN and tenant model
- **One Everee company instance per EIN** (Everee architectural constraint).
- New `payrollTenants` table. `stores.evereeCompanyId` FK (multiple stores can share one EIN).
- Each tenant gets its own API token + tenant ID (`x-everee-tenant-id` header).
- Pay frequency configured **per EIN** (weekly/biweekly/semi-monthly/monthly), not per store.

### Pay rate model
- Per employee + per position (matches Everee's position-compensation API).
- **MUST be effective-dated** — `effective_from`, nullable `effective_to`. Never overwrite `current_rate`. Historical shifts always resolve to the rate in effect at the time of the punch.

### Worker classifications (MVP)
- W-2 hourly + W-2 salaried only. 1099 contractors deferred to Phase 2.

### Scheduling provider gate
- Payroll is available ONLY when `Store.schedulingProvider = 'buyerkiosk'`.
- **WIW AND Homebase stores both excluded** — same ADR-5 exclusion pattern. See skill `buyerkiosk-wiw-exclusion-source-of-truth`. Used as carrot to migrate scheduling off these tools onto BK-native.

### Approval flow
- BK builds the pay run review UI on top of Everee data APIs.
- Owner reviews in BK, single deep-link click sends them to Everee for the final approve commit (Everee has no programmatic approval endpoint).

### Account model
- **Person-centric** (already mostly there in BK — unique employee IDs/emails/usernames).
- One BK User can have multiple Employment relationships (each with its own everee_worker_id, since each EIN gets a separate Everee worker record).
- Cross-merchant match-detection at hire time: prompt "this person already has a BK account from working at [Other Store] — link or create new?"
- Worker keeps BK login forever, accumulates pay history across multiple merchants (required for IRS 4-year W-2 access).

### Self-service in BK (employee-facing)
- Pay stubs viewer (in BK app)
- Real-time pay advance request (in BK app)
- Address / direct deposit / W-4 updates (embedded Everee components in BK shell)
- W-2 / year-end form download (subject to Everee bulk-retrieval API confirmation)

### Mobile parity at launch
- Pay stub viewer ✅
- Real-time pay advance request ✅
- PTO request submission ✅
- Onboarding (W-4/I-9/DD) — **requires desktop or tablet**, mobile onboarding deferred
- Profile updates — defer to web for MVP

### Termination workflow
- Manager hits "Terminate" → system orchestrates:
  - State-aware final paycheck (CA = immediate, MA/CO = 6 days, others = next regular payday or 7 days). Auto-build off-cycle pay run.
  - Auto-cancel all future scheduled shifts; notify scheduler.
  - Mark Everee worker SEPARATED via API; retain pay history.
  - Worker retains BK login forever (IRS retention).

### Punch edit policy
- **Punches LOCK after timesheet submission to Everee.** Manager must create a separate adjustment record.
- Free edits pre-submission only.
- Cleanest audit trail; required for high-stakes domain integrity.

### Multi-state handling
- **Webhook-driven only for MVP** — implement `worker.new-tax-forms-available` handler; surface as banner in worker profile.
- NO proactive blocking at scheduling time.
- NO proactive "warn at scheduling time" UI.
- Defer "auto-detect-at-schedule-time" enhancement to v2.

### Real-time pay (Everee Pay Card / on-demand earnings)
- **Headline differentiator at launch.** Workers opt in via embedded component.
- Advance-pay request UI lives in the existing BK Team app — same app workers use to clock in.

### Migration priority (existing customer providers)
1. ADP / Paychex CSV importer (highest customer count)
2. QBO Payroll (clean API export; customers already on QBO)
3. Homebase (more complex — requires scheduling migration prerequisite)

### Customer offboarding
- Full data export + Everee company handoff to direct-billing.
- Build into MVP, not as afterthought.
- We retain audit trail per IRS retention rules (see §12).

### Pilot model
- 5 hand-picked customers, white-glove launch.
- Our team on every pay run for first 2-3 cycles per customer.
- Then open the floodgate.
- **NO internal dogfooding** — BK Inc has no W-2 employees, so pilot is the first real-money test.

### Pre-launch readiness gate
- Hard automated gate, no bypass.
- Refuses to enable real payroll until: EIN configured, bank verified with Everee, COA mapping complete, all current employees onboarded in Everee, pay schedule confirmed, two-person approval threshold set, sandbox test pay run passed.

### Tips, 1099, trade credit
- **Tips**: never (resale doesn't tip). Add nullable `cashTips`/`creditTips` columns in Phase 0 to avoid future migration; otherwise feature permanently deferred.
- **1099 contractors**: never for MVP (not used in resale).
- **Trade credit as comp**: never (rare in resale).

### Launch market
- **All 50 states day 1.** Everee handles state tax compliance — white-labeling is exactly why we're not state-limited.

### Timeline
- No fixed external deadline.
- Internal target: first pilot live within 4-6 months.

---

## 4. New Surfaces Required

### 4.1 Data Layer (Schema)

All migrations to be authored as JSON in `userfrosting/migrations/input/` and applied via the existing `userfrosting/conductor` system. Per project rules, **never** modify tables directly. See skill `buyerkiosk-conductor-targeted-migration` for verifying migrations against dev stores.

**Central DB (`kiosk_buykiosk`):**

- `payrollTenants` — one row per EIN: `id`, `evereeCompanyId`, `evereeTenantId`, `evereeApiTokenEncrypted`, `legalName`, `ein`, `legalAddressLine1`, `legalAddressLine2`, `legalCity`, `legalState`, `legalZip`, `entityType` (LLC/Corp/SoleProp), `payFrequency` (weekly/biweekly/semi_monthly/monthly), `payPeriodEndsOnDayOfWeek`, `payCutoffHoursBefore`, `twoPersonApprovalThresholdCents` NULL, `provisionedAt`, `provisionedByUserId`, `isActive`, `brandingJson`.
- `payrollRuns` — `id`, `payrollTenantId`, `evereePayRunId`, `periodStart`, `periodEnd`, `status` (draft/submitted/funded/paid/failed/cancelled), `submittedByUserId`, `submittedAt`, `approvedByUserId`, `approvedAt`, `totalGrossCents`, `totalNetCents`, `totalEmployerTaxCents`, `totalEmployeeTaxCents`, `employeeCount`.
- `payrollRunLines` — `id`, `payrollRunId`, `userId`, `evereeWorkerId`, `regularHours` DECIMAL(8,4), `overtimeHours` DECIMAL(8,4), `doubletimeHours` DECIMAL(8,4), `ptoHours` DECIMAL(8,4), `bonusAmountCents`, `grossWagesCents`, `netWagesCents`, `evereePayableId`, `status`, `lineSnapshotJson` (snapshot of source punches + rate at submit time).
- `payrollRunSnapshots` (NEW, defense layer) — `id`, `payrollRunId`, `snapshotType` (pre_submit/post_approval/post_paid), `sourceDataJson` (full snapshot of punches, rates, classifications at moment of snapshot), `snapshotAt`.
- `payrollWebhookEvents` — `id`, `evereeEventId` UNIQUE, `evereeEventType`, `companyId`, `payload` (JSON), `receivedAt`, `processedAt`, `processingError`. Idempotency table.
- `payrollAuditLog` — extends `scheduleAuditLog` pattern: `id`, `userId`, `actionType` (rate_change/termination/onboard_kickoff/run_submit/run_approve/punch_adjustment/coa_change), `before` JSON, `after` JSON, `actorUserId`, `at`.
- `payRateHistory` — **effective-dated, non-negotiable**: `id`, `userId`, `payrollTenantId`, `positionId`, `rateType` (`hourly`/`salary_annual`), `rateCents` INT, `effectiveFrom` DATE NOT NULL, `effectiveUntil` DATE NULL, `setByUserId`, `createdAt`, `note`. Queries resolve rate by punch date.
  - Index: `(userId, payrollTenantId, positionId, effectiveFrom DESC)`
  - Never UPDATE; only INSERT new effective-dated rows.
- `payrollCoaMappings` — `id`, `payrollTenantId`, `positionId` NULL, `mappingType` (wage_expense/payroll_tax_expense/cash), `qboAccountId`, `qboAccountName`, `setByUserId`, `setAt`. Per-tenant + optional per-position.

**PTO tables (BK-owned, decided 2026-05-18):**
- `ptoAccrualPolicies` — `id`, `payrollTenantId`, `name`, `accrualType` (hours_per_hour_worked/lump_sum_annual/lump_sum_anniversary), `accrualRate` DECIMAL(8,6), `maxBalanceHours` DECIMAL(8,2) NULL, `carryoverHours` DECIMAL(8,2) NULL, `appliesTo` (all/hourly_only/salaried_only/specific_positions), `effectiveFrom`, `isActive`.
- `ptoAccrualBalances` — `id`, `userId`, `payrollTenantId`, `policyId`, `balanceHours` DECIMAL(8,2), `lastAccruedAt`, `lastUsedAt`.
- `ptoRequests` — `id`, `userId`, `payrollTenantId`, `startDate`, `endDate`, `hours` DECIMAL(8,2), `requestType` (pto/sick/personal), `status` (pending/approved/denied/cancelled), `requestedAt`, `approvedByUserId` NULL, `approvedAt` NULL, `note`, `payrollRunLineId` NULL (populated when paid out).

**Central DB users extension:**
- Extend `kiosk_users.users`: add `legalFirstName`, `legalLastName`, `dob`, `addressLine1`, `addressLine2`, `city`, `state`, `zip`, `phoneE164`. (Display name stays for UI; legal name is for payroll.)
- Add `evereeWorkerId` per user-per-tenant (since one BK user can have multiple Everee worker records under different EINs). Probably `userPayrollProfiles` table: `userId`, `payrollTenantId`, `evereeWorkerId`, `tinVerificationStatus`, `onboardingStatus`, `lifecycleStatus`, `realTimePayEnrolled` BOOL, `lastSyncedAt`.
- Add `employmentClassification` (`w2_hourly`/`w2_salaried`) to `userStoreAssignments` (or new `userEmployment` table for richer model).
- Add `annualSalaryCents` for salaried employees.

**Positions extension:**
- Add `workersCompClassCode` to positions.
- Add `qboWageAccountId` to positions (overrides tenant-default mapping if set).

**Scheduling time punches:**
- Add nullable `cashTipsCents` and `creditTipsCents` to `scheduleTimePunches` (Phase 0; tips never used in MVP but avoids future migration cost).
- Add `submittedToEvereeAt` TIMESTAMP NULL — populated when timesheet pushed; used to enforce punch lock policy.

### 4.2 Backend Services (PHP)

New module: `userfrosting/src/BuyerKiosk/Payroll/`

- `Clients/EvereeApiClient.php` — REST client with HTTP Basic Auth (`authorization: basic <base64(sk_...)>` + `x-everee-tenant-id: {id}` headers), retry logic, rate limit handling, structured exceptions, idempotency-key support.
- `Services/EvereeProvisioningService.php` — `provisionTenant(legalDetails)`: creates Company Instance via Everee API (or wraps the manual portal step if not API-available); stores `payrollTenants` row; mints+encrypts API token.
- `Services/EvereeOnboardingService.php` — `kickOffEmployeeOnboarding(userId, payrollTenantId)`: collects required PII from `users` table, calls `kick-off-onboarding-for-an-employee` Everee endpoint, returns onboarding URL/token for embed.
- `Services/PayrollRunService.php` — `createDraftRun(payrollTenantId, periodStart, periodEnd)`: aggregates from `scheduleTimesheets` (status='approved') across all stores under the tenant, pulls effective-dated rates from `payRateHistory`, computes per-line gross. `submitRun(runId)`: pushes to Everee Payables API with deterministic idempotency keys. `cancelRun(runId)`: while still draft.
- `Services/PayRateService.php` — `setRate(userId, payrollTenantId, positionId, rateType, rateCents, effectiveFrom, note)`, `getRate(userId, payrollTenantId, positionId, asOfDate)`, `listHistory(userId, payrollTenantId)`. Audit-logged. INSERT-only (never UPDATE).
- `Services/PtoAccrualService.php` (NEW) — `accrueForApprovedHours(payrollRunLineId)`, `getBalance(userId, payrollTenantId, asOfDate)`, `submitRequest(...)`, `approveRequest(...)`, `payOutBalance(userId, payrollTenantId)` (for termination final paycheck).
- `Services/EvereeWebhookHandler.php` — receives + verifies webhooks via HMAC, idempotently dispatches to handler per event type. **11 events to handle**: `worker.created`, `worker.profile-updated`, `worker.deleted`, `worker.onboarding-completed`, `worker.onboarding-locked`, `worker.tin-verification-status-changed`, `worker.new-tax-forms-available`, `payment.paid`, `payment.deposit-returned`, `payment.updated-payment-method`, `payment-payables.status-changed`. Deduplication via `payrollWebhookEvents.evereeEventId`.
- `Services/EvereeTokenStorage.php` — encrypts/decrypts per-tenant API tokens at rest using master key from env. Follow same pattern as existing `qbAccessToken` encryption.
- `Services/QboPayrollJeService.php` (NEW) — generates QBO journal entries from approved pay runs using `payrollCoaMappings` for per-position wage account coding. Watch out for `qbo-journalentry-totalamt-zero` skill — sum line items, never read `TotalAmt`.
- `Services/PayrollReconciliationService.php` (NEW) — daily job: pulls `GET /integration/v1/expenses/by-date-range` from Everee, compares to our `payrollRuns` ledger, alerts on drift. Catches webhook losses and silent breakage.
- `Services/PayrollOffboardingService.php` (NEW) — full data export for departing merchants + Everee company handoff to direct billing.
- `Controllers/PayrollAdminController.php` — endpoints for the Live/web admin UI.
- `Controllers/PayrollEmployeeController.php` — endpoints for the Team app earnings tab (mostly thin proxies to Everee for stubs/tax docs).
- `Controllers/EvereeWebhookController.php` — receives `POST /api/payroll/webhook/everee`, verifies HMAC, persists to `payrollWebhookEvents`, queues for processing.
- `Jobs/IngestEvereeWebhookJob.php` — TaskEngine job for async webhook processing.
- `Jobs/SyncEvereeWorkerJob.php` — periodic reconciliation of `userPayrollProfiles` with Everee state.
- `Jobs/DailyPayrollReconciliationJob.php` (NEW) — runs `PayrollReconciliationService` nightly per tenant.
- `Jobs/PtoAccrualJob.php` (NEW) — accrues PTO hours from approved timesheets per tenant's policies.

### 4.3 Routes

- `userfrosting/routes/payroll.php`:
  - `POST /admin/:typeNum/payroll/provision` — initiate Everee Company Instance creation (per EIN)
  - `POST /admin/:typeNum/payroll/employees/:userId/onboarding` — kick off employee onboarding (returns embed token)
  - `GET /admin/:typeNum/payroll/runs` — list runs
  - `POST /admin/:typeNum/payroll/runs` — create draft from approved timesheets
  - `GET /admin/:typeNum/payroll/runs/:runId/preview` — dry-run preview (gross/net per employee)
  - `POST /admin/:typeNum/payroll/runs/:runId/submit` — submit to Everee
  - `POST /admin/:typeNum/payroll/runs/:runId/cancel`
  - `GET /admin/:typeNum/payroll/employees/:userId/rate` — current rate
  - `POST /admin/:typeNum/payroll/employees/:userId/rate` — set new rate (effective-dated)
  - `GET /admin/:typeNum/payroll/employees/:userId/rate/history` — full history
  - `POST /admin/:typeNum/payroll/employees/:userId/terminate` — triggers state-aware final paycheck flow
  - `GET /admin/:typeNum/payroll/coa-mappings` — list COA mappings for tenant
  - `POST /admin/:typeNum/payroll/coa-mappings` — set/update COA mapping
  - `GET /admin/:typeNum/payroll/pto/policies` / `POST /admin/:typeNum/payroll/pto/policies`
  - `GET /admin/:typeNum/payroll/pto/requests` (manager view) / `POST /admin/:typeNum/payroll/pto/requests/:id/approve`
  - `POST /admin/:typeNum/payroll/punches/:punchId/adjust` — create adjustment record (since punches lock post-submission)
  - `POST /admin/:typeNum/payroll/offboard` — full data export + Everee handoff
- `userfrosting/routes/api.php` (mobile):
  - `GET /api/mobile/:typeNum/payroll/me/earnings` — YTD + last paycheck summary
  - `GET /api/mobile/:typeNum/payroll/me/embed-token/:component` — fetch a fresh Everee embed token for the requested component (PAYMENT_HISTORY / TAX_DOCUMENTS / PAYMENT_DEPOSIT / PAY_CARD_SIGNUP / WORKER_HOME / HOME_ADDRESS)
  - `GET /api/mobile/:typeNum/payroll/me/pto/balance`
  - `POST /api/mobile/:typeNum/payroll/me/pto/request`
  - `POST /api/mobile/:typeNum/payroll/me/advance-pay-request` — real-time pay advance via Everee on-demand earnings
  - `GET /api/mobile/:typeNum/manager/payroll/runs` — manager list view from Live app
  - `POST /api/mobile/:typeNum/manager/payroll/runs/:runId/submit`
- `POST /api/payroll/webhook/everee` — public-but-HMAC-verified webhook endpoint

### 4.4 Web Admin UI (Twig + Syncfusion EJ2)

Templates under `userfrosting/templates/themes/default/admin/payroll/`:

- `payroll-setup.html` — store-owner onboarding wizard:
  1. Legal entity details (name, EIN, address, entity type)
  2. Provision Company Instance (calls Everee)
  3. Embed Everee admin portal SSO link for the owner to complete bank/tax setup
  4. COA mapping (positions → QBO wage accounts)
  5. Two-person approval threshold (optional)
  6. Pre-launch readiness checklist with hard gate
  7. Sandbox test pay run
  8. Confirm + activate
- `payroll-employees.html` — employee roster with onboarding status, embedded `WORKER_HOME` admin view per employee, employment classification toggle (hourly/salaried)
- `payroll-rates.html` — rate management screen with effective-dated history table, "set new rate effective from" form, per-position rates
- `payroll-runs.html` — Syncfusion EJ2 Grid of runs with status badges (see skill `syncfusion-grid-hidden-tab-raf-defer` for known rendering gotcha). Drill-in to per-run line items.
- `payroll-run-detail.html` — **dry-run preview screen** showing gross/net per employee before submit. Includes deep-link button to Everee for final approval click.
- `payroll-settings.html` — pay schedule (weekly/biweekly/semi-monthly/monthly), cutoff time, default tax classification
- `payroll-coa-mapping.html` — wage GL account mapping per position
- `payroll-pto-policies.html` — PTO accrual policy setup
- `payroll-pto-requests.html` — pending PTO requests with approve/deny

JS modules under `public_html/js/admin/payroll/`:
- `payroll-setup.js` — wizard state machine
- `payroll-runs.js` — Grid binding, submit confirmation flow
- `payroll-dashboard-widget.js` — the owner dashboard tiles (see §4.10)
- `everee-embed-loader.js` — shared utility to fetch embed token + inject Everee iframe with our white-label theme

### 4.5 Live App (Manager) — Flutter

Path: `/Users/rvanvuren/Projects/buyerkiosk-live-flutter/lib/`

- `domain/entities/payroll/` — `PayRun`, `PayRunLine`, `PayrollEmployee`, `PayRate`, `PtoBalance`, `PtoRequest`
- `data/repositories/payroll_repository_impl.dart` — calls our backend payroll endpoints
- `presentation/providers/payroll/` — Riverpod providers for runs, rates, onboarding status, PTO requests
- `presentation/screens/payroll/`:
  - `payroll_dashboard_screen.dart` — next pay run countdown + approval status, YTD spend trend, action items (TIN failures, banking issues, new tax forms), daily labor cost vs schedule budget
  - `pay_run_list_screen.dart` — list with status filters
  - `pay_run_detail_screen.dart` — line items, dry-run preview, deep-link to Everee for final commit
  - `employee_payroll_setup_screen.dart` — kick off onboarding per employee, hosts Everee `ONBOARDING` component via `webview_flutter`
  - `pay_rate_screen.dart` — set/view effective-dated rates per employee+position
  - `termination_workflow_screen.dart` — state-aware final paycheck flow + future shift cancellation
  - `punch_adjustment_screen.dart` — for post-submission punch corrections
  - `pto_approval_screen.dart` — pending PTO requests
- `presentation/widgets/payroll/`:
  - `everee_embed_view.dart` — generic `webview_flutter` wrapper. See skill `flutter-dio-ssl-certificate-bypass` for dev-environment SSL handling. Watch out for type-erasure issues if using Ably-style platform-channel data (`ably-flutter-map-type-deep-conversion` skill).
- `core/services/payroll_notification_service.dart` — handle FCM payroll alerts (run failed, deposit returned, etc.)

### 4.6 Team App (Employee) — Flutter

Path: `/Users/rvanvuren/Projects/buyerkiosk-team/lib/`

- `domain/entities/earnings.dart` — `EarningsSummary`, `PayStubMeta`, `TaxDocMeta`, `PtoBalance`
- `presentation/screens/earnings/`:
  - `earnings_screen.dart` — top-level tab, shows YTD + last paycheck summary card; below, action tiles:
    - "Pay Stubs" → opens `PAYMENT_HISTORY` embed
    - "Tax Documents" → opens `TAX_DOCUMENTS` embed
    - "Direct Deposit" → opens `PAYMENT_DEPOSIT` embed
    - "Pay Card" → opens `PAY_CARD_SIGNUP` embed (instant pay opt-in)
    - "Cash Out Now" → real-time pay advance request (key differentiator — see skill `flutter-api-resilience-defensive-parsing` for resilience patterns)
    - "Address" → opens `HOME_ADDRESS` embed
  - `everee_embed_screen.dart` — same generic webview wrapper; reused across components
- `presentation/screens/pto/`:
  - `pto_request_screen.dart` — submit PTO request from mobile
  - `pto_history_screen.dart` — past requests
- `presentation/providers/earnings_provider.dart` — fetches summary + on-demand embed tokens
- New tab in main navigation: "Earnings" (between Schedule and Chat)
- During first-run, if a user is mid-onboarding, the home screen surfaces "Complete payroll setup" CTA — but routes to a **desktop browser link via email** (mobile onboarding deferred per 2026-05-18 decision)

### 4.7 Embed Component Strategy

All seven Everee components are loaded via the same `webview_flutter` (or web iframe) wrapper. Pattern:

1. Mobile app or web requests `GET /api/mobile/:typeNum/payroll/me/embed-token/:component` (or admin endpoint).
2. Backend mints a short-lived JWT/session token via Everee's API.
3. Backend returns `{ url: 'https://embed.everee.com/...', token: '...', themeOverrides: {...} }`.
4. Frontend loads URL with token. Everee renders the white-label component with our brand.
5. On completion / state change, Everee fires a webhook to us (e.g., `worker.onboarding-completed`).

The wrapper is **one widget**, reused across 7 components, ~200 lines of Flutter. The heavy lifting is in the token-mint endpoint.

### 4.8 Permissions

Add to `RoleConfigService` (`userfrosting/src/BuyerKiosk/TeamMember/Services/RoleConfigService.php`):

- `manage_payroll` — Owner only by default (per 2026-05-18 decision; no new dedicated Payroll Admin role for MVP)
- `submit_pay_run` — Owner + Manager
- `approve_pay_run` — Owner only (single-person approval)
- `approve_pay_run_above_threshold` — Owner + second user (when two-person approval threshold is set)
- `view_pay_run` — Owner + Manager + ShiftLead
- `set_pay_rate` — Owner only
- `view_own_earnings` — All employees (via Team app)
- `kickoff_employee_onboarding` — Owner + Manager
- `approve_pto_request` — Owner + Manager
- `request_pto` — All employees (own)
- `terminate_employee` — Owner + Manager (Owner approval required for final paycheck commit)
- `create_punch_adjustment` — Owner + Manager

Audit logging required on every action that requires `manage_payroll` or `set_pay_rate` or `terminate_employee`.

### 4.9 Notifications

New FCM categories (extend existing notification preference matrix):
- `payroll_run_submitted` — to all managers
- `payroll_run_funded` — to submitter
- `payroll_run_failed` — to submitter (urgent)
- `payment_paid` — to employee (their paycheck landed) — required per 2026-05-18 decision
- `payment_deposit_returned` — to employee + manager (urgent — ACH failure)
- `onboarding_completed` — to manager
- `onboarding_locked` — to manager (action required: failed verification)
- `tin_verification_failed` — to manager + employee
- `new_tax_forms_available` — to employee (W-2 / 1099 ready) AND to manager (heads-up on multi-state hire)
- `pay_run_approval_reminder` — to owner X hours before pay date if pay run not yet approved (required per 2026-05-18 decision)
- `pto_request_submitted` — to approving manager
- `pto_request_approved` / `pto_request_denied` — to requesting employee

Each routed through the existing granular notification matrix. Use existing email + push + SMS plumbing.

### 4.10 Owner Dashboard Tiles (decided 2026-05-18)

The Live app payroll dashboard surfaces four tiles:

1. **Next pay run countdown + approval status** — "Next pay run: Friday. Status: Draft. 12 employees, est. $14,230 gross. Tap to review."
2. **YTD payroll spend with month-over-month trend** — chart by store/position, pulled from Everee expenses API + schedule data for projections
3. **Pending action items** — new tax forms required, banking failures, exceptions (overtime spikes, missed punches preventing submission)
4. **Daily labor cost vs schedule budget** — today's actual vs scheduled, useful for shift-level cost control

---

## 5. Defense Layers for AI-Built Code (added 2026-05-18)

Payroll defects are federal liabilities, not support tickets. ALL of these are required, not optional:

1. **Strict Money type** — integer cents only. No float, no double. Compile-time errors when mixed with hours.
2. **Strict Hours type** — decimal with explicit precision. No floats.
3. **Invariant assertions** in every calculation function: `assert(sum(line_items) === gross_pay)`, `assert(no_negative_hours)`, `assert(no_shift_spans_more_than_18h)`. Fail loud in dev, alert in prod, never silently pass.
4. **Idempotency keys on EVERY mutating Everee API call.** Deterministic: `pay_run_{ein}_{period_end}_{shift_id}`. Retry-safe by construction.
5. **Snapshot-on-submit** — every push to Everee snapshots source data (punches, rates, classifications) at exact moment into `payrollRunSnapshots`. Audit trail IS the source data, not the calculation.
6. **Daily reconciliation job** — pull `GET /integration/v1/expenses/by-date-range`, compare to our ledger, alert on drift. Catches webhook losses + silent breakage.
7. **Pre-submission validation gate** — before any push to Everee: no punches without clock-outs, no shifts >18h, no future-dated punches, no employees missing required Everee profile fields. Fail in our UI, not Everee's.
8. **Webhook deduplication** by Everee's `id` field — persist every webhook in `payrollWebhookEvents`. Idempotently ignore duplicates.
9. **Dry-run preview UI** for owner before approval click. Real numbers shown in BK before any deep-link to Everee.
10. **Optional two-person approval threshold** — per-merchant setting, pay runs over $X require a second user to co-sign.

---

## 6. Hard Payroll-Domain Rules (Non-Negotiable Schema)

- **Pay rate records MUST be effective-dated** (`effective_from`, nullable `effective_to`). Never overwrite `current_rate`. Historical shifts must always resolve to the rate in effect at the time of the punch. INSERT-only.
- **Money type = integer cents, never float/double.** All monetary fields suffixed `_cents` (e.g., `grossWagesCents`).
- **Hours type = decimal with explicit precision** (DECIMAL(8,4) for hours, DECIMAL(8,2) for PTO balances). Never float.
- **IRS retention rules apply to us:**
  - W-4/W-2 records = 4 years after tax due date
  - Wage records = 4 years
  - I-9 = 3 years after hire OR 1 year after term, whichever is later
  - Customer offboarding cannot delete this data within retention window (handoff to merchant or retain ourselves)
- **Punches lock after submission to Everee.** `submittedToEvereeAt` is the lock signal. Adjustments require a new record, never a mutation.

---

## 7. Implementation Phases

### Phase 0 — Prerequisites (2-3 weeks)

Goal: clear all blockers before any payroll code is written.

- **Reconcile the two `Employee` classes** (`BuyerKiosk\Core\Employee` legacy + `BuyerKiosk\Employee\Employee` modern). Discrete refactor PR. Independent of all payroll decisions.
- **Verify person-centric account model** in code — confirm whether `userStoreAssignments` handles cross-merchant case. If gap exists, plan refactor here.
- **Confirm Everee sandbox tenant** with partner manager (Phase 0 dependency — without it, we cannot safely test pay runs).
- Schema migrations: `payrollTenants`, `payrollRuns`, `payrollRunLines`, `payrollRunSnapshots`, `payrollWebhookEvents`, `payrollAuditLog`, `payRateHistory`, `payrollCoaMappings`, `ptoAccrualPolicies`, `ptoAccrualBalances`, `ptoRequests`, `userPayrollProfiles`, plus extensions to `users`, `positions`, `scheduleTimePunches`.
- **Background job/queue infrastructure** documentation — confirm what BK has today for async submission, retries, scheduled jobs.
- COA mapping UI design (positions → QBO wage accounts).
- Partner manager email kickoff (see §13).

**Deliverable**: clean foundation; no customer-visible features yet.

### Phase 1a — Foundations (3-4 weeks)

Goal: backend talks to Everee sandbox, stores tenants, stores rates, receives webhooks.

- `EvereeApiClient` with sandbox creds, basic CRUD against Workers + Companies
- `EvereeProvisioningService` — per-EIN tenant provisioning
- `EvereeTokenStorage` — encrypted at rest
- `PayRateService` with effective-dated history (INSERT-only, audit-logged)
- `EvereeWebhookHandler` + `EvereeWebhookController` + idempotency
- HMAC verification
- Permissions added to `RoleConfigService`
- One-time backfill admin tool: owner enters initial pay rates for existing employees
- Embedded `ONBOARDING` component in web admin

**Deliverable**: a backend that can talk to Everee sandbox, with manual worker sync.

### Phase 1b — Pay Run Plumbing (4-6 weeks)

Goal: store owner can complete an end-to-end sandbox pay run.

- Web admin: `payroll-setup.html` provisioning wizard (with pre-launch readiness gate)
- Web admin: `payroll-employees.html` roster + onboarding kickoff
- Web admin: `payroll-rates.html` rate management
- Web admin: `payroll-runs.html` + `payroll-run-detail.html` (dry-run preview)
- Live app: `payroll_dashboard_screen.dart` + `pay_run_list_screen.dart` + `pay_run_detail_screen.dart` + `everee_embed_view.dart`
- `EvereeOnboardingService` + `PayrollRunService` complete
- Salary employee model (annualSalaryCents, exempt flag wiring)
- Pay stub viewer in Team app
- All 11 webhook handlers implemented

**Deliverable**: store owner can run a complete pay run on sandbox.

### Phase 1c — Differentiators (4-5 weeks)

Goal: the things that make this competitive, not just functional.

- **Real-time pay opt-in flow** + advance-pay request UI (Team app)
- **PTO accrual engine** — `PtoAccrualService`, accrual job, request/approval flow on Live + Team apps
- **QBO journal entry generator** with COA mapping UI
- All FCM payroll notifications wired through
- **Daily reconciliation job** running on schedule
- Embedded W-4/DD/address updates in Team app

**Deliverable**: full differentiator stack working in sandbox.

### MVP Launch Ready (2-3 weeks)

- State-aware **final paycheck workflow** at termination
- **Auto-cancel future shifts** on termination
- **Bonus / off-cycle pay** flow
- **Bulk migration importer** (ADP/Paychex CSV first)
- **Two-person approval threshold** (optional per-merchant)
- **Punch adjustment workflow** (post-submission)
- **Customer offboarding flow** (data export + Everee handoff)
- All defense layers verified (assertions, idempotency, snapshots, reconciliation, validation gate)
- Customer-support runbooks
- Help-center articles via `support_articles` system

**Deliverable**: production-ready, all integrity guarantees in place.

### Pilot launch

- 5 hand-picked customers, white-glove
- Our team on every pay run for first 2-3 cycles per customer
- Tight feedback loop, fix any defects before next batch
- Then open the floodgate

### Phase 2 — Post-launch

- 1099 contractors (if any customer asks)
- Tips (if any vertical shift) — columns already in place from Phase 0
- Mid-year YTD migration
- Proactive multi-state alerts at scheduling time
- Mobile onboarding flow
- Additional verticals if expanding beyond resale clothing

---

## 8. Effort Summary

| Phase | Backend | Flutter | Web | Calendar |
|---|---|---|---|---|
| Phase 0 — Prerequisites | 6 | 0 | 1 | 2-3 weeks |
| Phase 1a — Foundations | 10 | 0 | 1 | 3-4 weeks |
| Phase 1b — Pay Run Plumbing | 10 | 8 | 6 | 4-6 weeks |
| Phase 1c — Differentiators | 10 | 6 | 3 | 4-5 weeks |
| MVP Launch Ready | 6 | 3 | 2 | 2-3 weeks |
| **Total to pilot-ready** | **~42 days** | **~17 days** | **~13 days** | **~15-21 weeks** |

For 1 backend engineer + 1 Flutter engineer + part-time web frontend engineer working in parallel with AI assistance: **~4-5 months elapsed** to production pilot-ready.

No fixed external deadline — quality-first. Internal milestone: first pilot live within 4-6 months.

---

## 9. Strategic Positioning

After integration ships, the BuyerKiosk pitch becomes:

> "POS. Scheduling. Payroll. One platform. One bill. One login. Hours flow from clock-in to paycheck without spreadsheets. Tax filing is automatic. Employees get instant pay through the same app they clock in with."

**Five competitive moats** unique to BK's resale customer base:

1. **Single-vendor consolidation** vs. POS + WIW/Homebase + ADP/QBO Payroll stacks (current stack for most independent resale stores).
2. **Hours-to-paycheck integrity** — punches flow through to pay run with zero export/import. No customer-side reconciliation.
3. **Real-time pay inside the timeclock app** — workers tap "cash out" right after clocking out. Square has this only because Square owns the POS. We own the timeclock.
4. **QBO journal entries auto-generated from payroll** — Everee has no GL export. Nobody else does this with a white-label payroll provider. Real moat.
5. **Person-centric pay history** — workers keep their BK account forever, pay history follows them across employers. Recruitment lever in tight labor markets.

**Risk to manage**: payroll errors are loud. A single $0 pay run lands on Twitter. The defense layers in §5 + the white-glove pilot model in §11 are how we manage this risk.

---

## 10. Migration Tooling Priority (added 2026-05-18)

Existing customer payroll providers concentrated in three providers. Build migration tools in this order:

| Source | Migration path | Priority | Notes |
|---|---|---|---|
| **ADP / Paychex** | CSV importer for employee list (name, SSN, address, bank, YTD subject to deferral). Cut-over at pay period end. | First (highest customer count) | ADP exports are messy but well-known format |
| **QuickBooks Payroll** | Export from QBO directly via API. Customer is already OAuth'd to QBO through our existing integration. | Second | Cleanest of the three |
| **Homebase** | Per WIW exclusion pattern — they have to migrate scheduling first (Homebase scheduling → BK-native). Then employee data via Homebase API (we already have Homebase integration). | Third | Two-step migration |

All migrations follow the same model: **clean cut-over at pay period boundary**, no parallel-run, no mid-year YTD ingestion (deferred to Phase 2).

---

## 11. Pilot Model

- **5 hand-picked customers** for the first batch
  - Criteria: existing happy customer, single-state preferred, willing to be a guinea pig, owner is engaged
- **White-glove launch**: our team (customer success rep) on every pay run for the first 2-3 cycles per customer
- After each customer ships 2-3 clean pay runs, open to next batch
- Total pilot: ~6 weeks of intensive customer-success time

**No internal dogfooding** — BK Inc has no W-2 employees, so the 5-customer pilot is the first real-money test. Mitigated by:
- All defense layers in §5 in place before pilot
- Pre-launch readiness gate in §4.4
- Sandbox test pay run required before going live per customer

---

## 12. Compliance & Retention

### IRS retention requirements (apply to us through Everee)
- W-4 + W-2 records: keep 4 years after tax due date
- Wage records: keep 4 years
- I-9: keep 3 years after hire OR 1 year after termination, whichever is later

**Implication**: customer offboarding cannot delete this data within the retention window. Handoff to merchant or retain ourselves.

### State final-paycheck laws (termination workflow)
- **CA**: immediate at termination
- **MA, CO**: within 6 days or next regular payday (varies)
- Most states: next regular payday or 7 days
- Workflow surfaces the correct deadline per worker's work state

### New-state hire detection
- Everee fires `worker.new-tax-forms-available` webhook when an employee's address state differs from their work state
- Surface as banner in worker profile (BK admin) — no proactive blocking at scheduling time per 2026-05-18 decision
- Merchant must register with new state's DOR before first paycheck in that state — Everee guides but does not do this

### Person-centric account model (compliance angle)
- IRS 4-year W-2 access requires workers to be able to access historical W-2s after leaving an employer
- Workers retain BK account forever; pay history view spans multiple employers
- Cross-merchant match-detection at hire time avoids duplicate accounts

---

## 13. Items Still Open for Everee Partner Conversation

Email these to partner manager BEFORE starting Phase 1a build (Phase 0 can proceed in parallel since it doesn't touch Everee APIs):

1. **Sandbox tenant** availability + how it differs from production (real-money risk?)
2. **Pricing tier** for our integration volume (per-active-employee + per-payment rates, minimum commit)
3. **Idempotency-key support** on all POST endpoints
4. **Bulk W-2/1099 retrieval** API (gap in public docs — needed for Team app W-2 download)
5. **Full webhook event enumeration** with sample payloads (docs only show a subset)
6. **Co-branded / white-labeled support** availability (their reps answering as us)
7. **Co-marketing** for white-label launches
8. **ACH funding timing** (T-1, T-2?) and merchant funding requirements
9. **Pay-frequency mix per EIN** — can one company have hourly weekly + salaried biweekly?
10. **Multi-EIN parent account management** — or is each instance truly standalone?
11. **Self-serve provisioning** API (vs portal-only Company Instance creation)
12. **Pay-run preview** endpoint shape (gross/net before submit)
13. **Off-cycle / correction-run** flow specifics
14. **Multi-store / multi-tenant employee handling** — one Worker record vs multiple per EIN
15. **E-Verify** inclusion in ONBOARDING component
16. **HMAC algorithm** for webhook signing + secret rotation mechanism
17. **SLA on tax filing accuracy** + remediation responsibility for filing errors
18. **Data portability / export** if we need to switch providers
19. **Pay card fee structure** (per-card-per-month) and whether end-customer or BuyerKiosk pays
20. **PTO/leave handling** — does Everee track PTO at all, or do we own it completely?

### Decisions made on items that were open in May 8 analysis
- ✅ Target market (resale clothing only)
- ✅ Support tier (Everee paycheck / BK app)
- ✅ Pricing model (we pay Everee, single bundled bill to merchant)
- ✅ EIN mapping (store-group level, multiple stores per EIN)
- ✅ PTO ownership (BK owns)
- ✅ Tips (never)
- ✅ 1099s (never for MVP)
- ✅ Salary employees (yes for MVP)
- ✅ Person-centric accounts (already mostly there)
- ✅ Worker post-termination access (permanent via BK)
- ✅ Multi-state strategy (webhook-driven, reactive)
- ✅ Homebase exclusion (same as WIW)
- ✅ Real-time pay (launch headline)
- ✅ QBO JE auto-post (Phase 1)
- ✅ Punch lock policy (post-submission)
- ✅ Termination workflow
- ✅ Pre-launch readiness gate (hard automated, no bypass)
- ✅ Customer offboarding (full export + handoff)
- ✅ Pilot model (5-customer white-glove)
- ✅ Mobile parity (pay stubs + advance + PTO; no mobile onboarding for MVP)
- ✅ Launch market (all 50 states day 1)
- ✅ Launch timeline (no fixed deadline, internal 4-6 month target)
- ✅ Punch edits after submission (locked, adjustment workflow required)

---

## 14. Pre-Flight Checks Before Phase 0

Three cheap pre-flight tasks before Phase 0 closes:

1. **Pay-rate completeness**: audit existing customer rosters. For pilot stores, manually capture rates and confirm there's a workable migration story (CSV import or manual entry).
2. **`scheduleTimePunches.punchType` enum check**: same pre-flight as the WhenIWork roadmap — confirm enum vs. varchar.
3. **`uf_user.display_name` → `legalFirstName/legalLastName` migration**: write the data-migration logic to split display_name into legal name fields. Many users will have nicknames stored; need a UX for legal-name-confirmation during the first onboarding.
4. **Person-centric account verification** (added 2026-05-18): verify `userStoreAssignments` handles cross-merchant case properly. If not, plan refactor into Phase 0.
5. **Two-Employee-class consolidation** (added 2026-05-18): see §2 critical gap. Discrete refactor PR, independent of payroll decisions.
6. **Background job infrastructure audit** (added 2026-05-18): document existing queue/scheduler, identify gaps for async webhook processing, daily reconciliation, PTO accrual jobs.

---

## 15. Action Items This Week

**You:**
1. Email Everee partner manager with the §13 question stack
2. Survey current payroll providers across customer base (even informal)
3. Identify the 5 pilot candidates

**Engineering (parallel to spec work):**
1. Verify person-centric account model in code
2. Reconcile the two `Employee` classes (Phase 0 prerequisite, can start now)
3. Document existing background job/queue infrastructure

**Spec phase (next 1-2 weeks):**
1. Write PRD for Phase 0 + Phase 1a using `/start:specify` (one PRD per phase, not a single mega-PRD)
2. Run `/prd-review` for Codex feedback
3. Then SDD for the same scope; repeat review

---

## 16. Comparison to Alternative Providers (reference)

| Provider | Embed components | API depth | Tax filing | Money movement | Best for |
|---|---|---|---|---|---|
| **Everee** | 7 ready-made (incl. Flutter wrapper) | Strong on workers, payables, onboarding | Yes, all 50 states | Yes (ACH + instant + pay card) | Vertical SaaS embedders, gig/hourly workforces |
| **Check** | API-first, you build UI | Most flexible | Yes | Yes | Builders who want full UI control |
| **Gusto Embedded** | Mirrors Gusto SMB UI | Strong on benefits/HRIS | Yes | Yes | Traditional W-2 small business |
| **Zeal** | API-first | Solid | Yes | Yes | Builders, technical teams |
| **Finch** | n/a (read-only) | HRIS data only | No | No | Reading employee data from existing HRIS, not running payroll |

**Why Everee for BuyerKiosk specifically**:
- Pre-built Flutter wrapper in their Flutter SDK shortens our mobile lift.
- Instant pay + pay card is a strong recruitment lever for our customers' hourly workforces.
- Their stated ICP (hourly, gig, non-9-to-5) matches our resale-store customer base.
- White-label admin portal saves building one ourselves.

**When to revisit Check or Zeal**: if Everee's PaaS pricing comes back uneconomic, or we hit limits on their embed components and want fully native UI control.

---

## Appendix A — Sources

- https://www.everee.com/
- https://www.everee.com/technology/
- https://www.everee.com/embed-pay/
- https://www.everee.com/pricing/
- https://developer.everee.com/docs/introduction
- https://developer.everee.com/docs/authentication-api-tokens
- https://developer.everee.com/docs/everee-embed
- https://developer.everee.com/docs/white-label-integration-overview
- https://developer.everee.com/docs/events-overview
- https://developer.everee.com/docs/worker-data-and-onboarding
- https://developer.everee.com/reference/createpayable
- https://developer.everee.com/reference/kick-off-onboarding-for-an-employee
- Local: `/Users/rvanvuren/Projects/buyerkiosk-web/everee-docs/` (full downloaded Everee documentation)

---

## Appendix B — File Pointers (Existing Infrastructure)

- `userfrosting/src/BuyerKiosk/Scheduling/Models/TimePunch.php`
- `userfrosting/src/BuyerKiosk/Scheduling/Models/Timesheet.php`
- `userfrosting/src/BuyerKiosk/Scheduling/Services/TimesheetExporter.php`
- `userfrosting/src/BuyerKiosk/Scheduling/Services/LaborCostCalculator.php`
- `userfrosting/src/BuyerKiosk/Scheduling/Services/OvertimeCalculator.php` — jurisdiction-aware OT (US-FLSA, California, Canadian provinces)
- `userfrosting/src/BuyerKiosk/Scheduling/Repositories/TimePunchAuditRepository.php` — immutable audit trail
- `userfrosting/src/BuyerKiosk/Scheduling/Repositories/ShiftAuditRepository.php` — immutable audit trail
- `userfrosting/src/BuyerKiosk/Auth/Models/StoreAssignment.php`
- `userfrosting/src/BuyerKiosk/TeamMember/Services/RoleConfigService.php`
- `userfrosting/src/BuyerKiosk/Core/Employee.php` — legacy class (Phase 0 consolidation target)
- `userfrosting/src/BuyerKiosk/Employee/Employee.php` — modern class (Phase 0 consolidation survivor)
- `userfrosting/src/BuyerKiosk/Core/Store.php` — has `payPeriodStart`, `schedulingProvider`, state field
- `userfrosting/src/BuyerKiosk/Core/AblyPublishThrottle.php` — real-time event infrastructure
- `userfrosting/src/BuyerKiosk/QuickBooks/` (existing GL integration; we extend for payroll JEs)
- `userfrosting/migrations/input/` (migration JSON pattern — see skill `buyerkiosk-conductor-targeted-migration`)
- `userfrosting/conductor` (migration runner)

## Appendix C — Related Skills

Project-specific skills that apply to payroll work:
- `buyerkiosk-wiw-exclusion-source-of-truth` — WIW/Homebase exclusion pattern
- `qbo-journalentry-totalamt-zero` — QBO JE generation trap (sum lines, never read TotalAmt)
- `buyerkiosk-conductor-targeted-migration` — testing migrations against a single dev store
- `syncfusion-grid-hidden-tab-raf-defer` — known EJ2 Grid rendering gotcha
- `flutter-api-resilience-defensive-parsing` — defensive Dio/Freezed parsing
- `flutter-dio-ssl-certificate-bypass` — dev environment SSL
- `ably-flutter-map-type-deep-conversion` — Ably platform-channel type erasure
- `csrf-token-refresh-spa-pattern` — for the single-page admin UI

## Appendix D — Decision Log

Decisions made during the 2026-05-18 architectural decisions session. Recorded in chronological order for context.

1. **Source of truth = split** (BK owns employment + pay rate; Everee owns PII + banking + tax forms)
2. **Approval flow = BK review UI + deep-link to Everee for final commit**
3. **EIN model = store-group level mapping** (multiple stores can share an EIN)
4. **Tips = no MVP** (resale doesn't tip), nullable columns added Phase 0 for future
5. **Worker types = W-2 hourly + W-2 salaried only** (no 1099 for MVP)
6. **WIW + Homebase stores excluded** (BK-native scheduling only — payroll as carrot to migrate)
7. **Real-time pay (Everee Pay Card) = headline differentiator at launch**
8. **Migration model = clean cut-over at pay period boundary** (no parallel-run, no YTD ingestion in MVP)
9. **Pay rate model = per employee + per position** (effective-dated, INSERT-only)
10. **Admin role = Owner/franchisee** (no new dedicated Payroll Admin role for MVP)
11. **Self-service in BK = pay stubs + advance + W-4/DD/address + W-2** (all four, full coverage)
12. **PTO ownership = BK** (accrual engine, balances, request flow; hours pushed to Everee at pay time)
13. **Pay frequency configured per EIN** (not per store)
14. **Off-cycle pay scope = final paychecks + bonuses** (commission + reimbursement deferred)
15. **Multi-state = webhook-driven reactive only** (no proactive scheduling-time alerts in MVP)
16. **QBO JE generation = Phase 1** (real competitive moat — Everee has no GL export)
17. **Pricing/billing = we pay Everee, single bundled subscription to merchant** (true white-label)
18. **Launch market = all 50 states day 1** (Everee handles state tax compliance)
19. **Support model = Everee tier-1 for paycheck questions, BK tier-1 for app**
20. **Worker post-termination access = permanent** via BK account (IRS retention + recruitment lever)
21. **Mobile parity at launch = pay stub viewer + advance request + PTO requests** (no mobile onboarding for MVP)
22. **Customer offboarding = full data export + Everee company handoff** (in MVP, not afterthought)
23. **Person-centric accounts confirmed** (already mostly there; verify in code)
24. **Termination workflow = state-aware final paycheck + auto-cancel future shifts + Everee SEPARATED + retain pay history**
25. **Owner dashboard = next pay run countdown + YTD spend trend + action items + daily labor cost** (four tiles)
26. **Pre-launch readiness = hard automated gate** (no bypass)
27. **Homebase = same exclusion as WIW** (BK-native scheduling only)
28. **No internal BK dogfooding** (BK Inc has no W-2 employees)
29. **Punch edits after submission = locked** (adjustment record required)
30. **Migration tooling priority: ADP/Paychex first, QBO Payroll second, Homebase third**
31. **Target market clarification: resale clothing stores only**, NOT general payroll SaaS — drives all scope decisions
32. **No fixed launch deadline; internal target 4-6 months to first pilot**
