---
title: "Carryforward watch"
url: https://services.dev/docs/examples/tax/carryforward-watch
captured: [tax-build.txt, tax-cases.txt, tax-check.txt, tax-years.txt]
---
# Carryforward watch

URL: https://services.dev/docs/examples/tax/carryforward-watch

> The steward a taxpayer keeps for the dates a return leaves on it. $9 a year, the brand answers for each carryforward's expiry, gives notice 180 days out, and sends a letter each year of what is still open.

*tax's words: return is a job, taxpayer is a subject, review is a task, preparer is a member (examples/tax/brand.ts).*

A return leaves dates behind it: the day a credit carried forward expires, and the days refund claims and the IRS's time to assess close. The annual return names Carryforward Watch as the taxpayer's `steward`, so those dates have an owner once no plan runs. For $9 a year, the brand answers for them.

```bash
cat services/carryforward-watch.ts
```

```txt title="magic values: none"
import { Service } from 'services.dev'
import { earliestExpiry } from '../lib/tax.ts'

// The steward a taxpayer keeps once no plan runs: it answers for the dates a return leaves on the subject. The brand
// owns the carryforwards' expiry, gives notice 180 days out, and sends a letter each year of what is still open.
export default Service({
  name: 'Carryforward Watch',
  description: 'Carryforwards, watched until they expire.',
  input: { owner: 'party: who hears the notice', ein: 'text: such as 12-3456789' },
  output: { letter: 'file: what is still open, and when it expires' },
  subject: { kind: 'taxpayer', key: 'ein' },
  deliver: { letter: { by: 'ai', cite: 'the carryforwards the taxpayer keeps' } },
  clocks: { expiring: { due: earliestExpiry, owner: 'brand', lives_on: 'subject', rungs: ['notice 180d'] } },
  price: { usd: 9, every: 'year' },
})
```

```bash
npx services.dev check
```

```txt title="magic values: none"
          expiring · a date your code decides · the brand · on the taxpayer
services/carryforward-watch.ts · 8 lines · $9 per year, charged at the start of each year.
  clocks  expiring · a date your code decides · the brand · on the taxpayer
  plan    Launch (services.dev) · subject at :11 · clocks.lives_on: 'subject' at :13 · price.every at :14
```

## The dates it keeps

`earliestExpiry` reads the carryforwards the taxpayer keeps and returns the first to expire. Acme's 2026 return used up the 2025 federal credit, so its earliest is now the 2026 credit, $13,800, on 31 December 2046:

```txt
→ GET /taxpayers/sbj_7Hq2
```

```txt title="magic values: owner.email = signs@example.test, metadata.sandbox.asks = {"organizer.books":"after 160d","organizer.assets":"waive","organizer #2":"after 2d","w9":"after 19d"}, metadata.sandbox.outside = {"reject":{"file.US-NY":["ein_mismatch"]}}, metadata.sandbox.events = { notice.received: { at: 2027-11-14T15:00:00Z, data: { notice, reply_by, tax_years } } }"
  keeps   carryforwards 2025    US credit 2025 $8,370, US-CA credit 2025 $6,537 · job_4Tx2 at compute · 2026-02-01
  keeps   carryforwards 2026    US credit 2026 $13,800, US-CA credit 2025 $331, US-CA credit 2026 $12,000 · job_4Tx3 at compute · 2027-07-20
  clocks  assessment and refund, 2025: 2029-04-17 · 2026: 2030-07-11 · expiring 2046-12-31, US credit 2026 $13,800 · each the brand's, the refunds mbr_8Ea1's
```

## When the plan ends

A client who leaves gets each date back in a letter, with the watch offered to keep them. The brand answers for each date it keeps, and the signer of record stays on each return until its assessment date:

```txt
→ GET /portal/subjects/sbj_7Hq2/letter
```

```txt title="captured/tax-cases.txt · 200 · the disengagement letter · Acme Robotics · 2029-01-20 · magic values: owner.email = signs@example.test, metadata.sandbox.outside = {"reject":{"file.US-NY":["ein_mismatch"]}}"
  Your Tax Plan ended on 20 January 2029. These dates are still running, and from today they are yours to keep:
    2029-04-17  refund claims on your 2025 return close, and so does the IRS's time to assess it
    2030-07-11  the same, for your 2026 return
    2031-04-18  the same, for your 2027 return
    2046-12-31  your earliest carryforward expires, $13,800 of US credit from 2026
  Katherine Johnson, EA, stays the signer of record on each return until its date. Keep them with Carryforward Watch for $9 a year, and we answer for them; or confirm each is yours.
```

[Subjects](https://services.dev/docs/service/subject.md#every-open-clock-has-an-owner) covers who owns a subject's clocks, and [Two clients, over the years](https://services.dev/docs/examples/tax/clients.md#a-client-who-leaves) the cancel.

---

- Up: [The tax example](https://services.dev/docs/examples/tax.md)
- Previous: [Amended return](https://services.dev/docs/examples/tax/amended-return.md)
- Next: [Year-end close](https://services.dev/docs/examples/tax/year-end-close.md)
