Tax Plan
One subscription a business buys once a year, routed to six Services, five inside allowances and the amendment at its own price. Schedules order the 1099s, the return and each quarter's estimate on dates the Services derive, and events order a question, a notice response or an amendment.
tax's wordsreturn is a jobtaxpayer is a subjectreview is a taskpreparer is a member
The Tax Plan is a Service whose work is other Services. Its on key routes the year: five days after each calendar year, its 1099s; a month after each tax year ends, that year's return; ten days before each quarter's payment is due, a C corp's estimate; and a question, a notice or a restated figure whenever one arrives. Its price is a year, and includes sets how much of each that year covers.
$ cat services/tax-plan.ts
import { Service } from 'services.dev'
import amendedReturn from './amended-return.ts'
import annualReturn from './annual-return.ts'
import estimate from './estimate.ts'
import informationReturns from './information-returns.ts'
import noticeResponse from './notice-response.ts'
import question from './question.ts'
// The plan a business buys. Its year routes to small Services with their allowances: five days after each calendar
// year, its 1099s; a month after each tax year ends, that year's return, and for a client who joins mid-year any year
// still open; ten days before each quarterly payment, a C corp's estimate; a question or a notice when one comes; and an
// amendment, at its own price, when a figure a later year read is restated. Past an allowance, the next is offered.
export default Service({
name: 'Tax Plan',
| Key | Here | What it does |
|---|---|---|
on.schedule.information | each: 'year', at: '5d after end' | Mints the 1099s for each calendar year, whatever the tax year, five days after it ends |
on.schedule.annual | each: 'tax_year', at: '1mo after end' | Mints the return for each tax year a month after it ends, on the client's own year end |
catch_up | 'open' | A client who joins mid-year gets every period whose date is still open, minted at once, and none whose date has passed |
on.schedule.estimate | each: 'quarter', at: '10d before pay' | Mints each quarter's estimate ten days before its own pay clock is due, so the dates come from lib/tax.ts, never from the plan |
when | sub => sub.input.entity === 'C corp' | Reads the subscription as it stands, so a client who changes entity changes what the next mint does |
on.event | question.asked, notice.received, fact.restated | An event sent to POST /events mints the Service it names. It carries your own id, so one sent twice mints once. A restated figure mints the amendment, outside the allowances, at its own price |
price.every | 'year' | The order is a subscription, sbn_…, charged at the start of each cycle |
price.includes | 1 return, 25 payees' 1099s, 4 estimates, 12 questions, 2 notices | Allowances per cycle. Inside one a job charges $0 and is counted; past it, the next is offered at its own price. Renewal resets them |
Every minted job shares the Tax Plan's taxpayer, and names the subscription it came from.
The business orders the Tax Plan like any Service. The answer is a subscription: its cycle, its allowances, and what each schedule and event will order next. Bought on 20 January, the plan catches up the 1099s still open:
→ POST /returns {"service":"tax-plan","business":{"name":"Acme Robotics","email":"books@acme.example"},"owner":{"name":"Ada Lovelace","email":"ada@example.com"},"ein":"12-3456789","entity":"C corp","jurisdictions":["US","US-CA","US-NY","US-NJ"],"books":"https://books.example/acme","max_usd":2400,"key":"plan-2027"}← sbn_7Hq2 · tax-plan · active · cycle 1 · 2027-01-20 → 2028-01-20 · $2,400.00 per year
allowances annual-return 0 of 1 · information-returns 0 of 25 · estimate 0 of 4 · question 0 of 12 · notice-response 0 of 2
minted 2027-01-20 catch_up open → job_4Tp0 information-returns · period 2026 · due 2027-02-01, rolled from 2027-01-31
schedule information → information-returns · next 2028-01-05 (5d after end 2027-12-31)
schedule annual → annual-return · next 2027-02-01 (1mo after end 2026-12-31)
schedule estimate → estimate · next 2027-04-05 (10d before pay 2027-04-15) · C corp
event question.asked → question
event notice.received → notice-response
event fact.restated → amended-return · outside the allowances, at $900.00A month after 2026 ends, the schedule mints the 2026 return and draws on the allowance. The return costs the business nothing more:
→ POST /test_clocks/default/advance {"to":"2027-02-02T00:00:00Z"} 2027-01-20 job_4Tp0 information-returns · 5 payees filed · allowance 5 of 25
2027-02-01 sbn_7Hq2 schedule annual → job_4Tp1 annual-return · period 2026 · $0.00 · allowance 1 of 1The owner's bookkeeping system sends a question and then a notice. Each event mints its Service inside the allowance:
→ POST /events {"type":"question.asked","id":"Q-0001","data":{"ein":"12-3456789","question":"Can we deduct the van?"}}← subscription.minted · event question.asked → job_4Tp2 question · $0.00
→ POST /events {"type":"notice.received","id":"CP161-0001","data":{"ein":"12-3456789","notice":"cp161.pdf","reply_by":"2027-03-01","tax_years":["2025"]}}
← subscription.minted · event notice.received → job_4Tp3 notice-response · $0.00
→ POST /events {"type":"notice.received","id":"CP161-0002","data":{"ein":"12-3456789","notice":"cp161.pdf","reply_by":"2027-04-01","tax_years":["2025"]}}
← subscription.minted · event notice.received → job_4Tp4 notice-response · $0.00A third notice finds the allowance spent. It isn't refused: the next answer is offered at the Service's own price, and the Tax Plan keeps the list of what it minted:
→ POST /events {"type":"notice.received","id":"CP161-0003","data":{"ein":"12-3456789","notice":"cp161.pdf","reply_by":"2027-05-01","tax_years":["2025"]}}← subscription.minted · event notice.received → notice-response offered at $299.00
← sbn_7Hq2 · tax-plan · active · cycle 1 · 2027-01-20 → 2028-01-20 · $2,400.00 per year
allowances annual-return 1 of 1 · information-returns 5 of 25 · estimate 0 of 4 · question 1 of 12 · notice-response 2 of 2
schedule information → information-returns · next 2028-01-05 (5d after end 2027-12-31)
schedule annual → annual-return · next 2028-02-01 (1mo after end 2027-12-31)
schedule estimate → estimate · next 2027-04-05 (10d before pay 2027-04-15) · C corp
event question.asked → question
event notice.received → notice-response
event fact.restated → amended-return · outside the allowances, at $900.00
minted 2027-01-20 catch_up open → job_4Tp0 information-returns · period 2026 · $0.00
minted 2027-02-01 schedule annual → job_4Tp1 annual-return · period 2026 · $0.00
minted 2027-02-02 event question.asked → job_4Tp2 question · $0.00
minted 2027-02-02 event notice.received → job_4Tp3 notice-response · $0.00
minted 2027-02-02 event notice.received → job_4Tp4 notice-response · $0.00
minted 2027-02-02 event notice.received → notice-response offered at $299.00A year, and the next runs the Tax Plan through a whole year and its renewal, and two clients a change, a cancel and a late start. Schedules and triggers covers on, and Subscriptions and allowances what a plan charges.