---
title: "What a member sees, and when"
url: https://services.dev/docs/people/pool/disclosure
captured: [task-sheet.txt, task-teaser.txt]
---
# What a member sees, and when

URL: https://services.dev/docs/people/pool/disclosure

> A teaser that never names a party, a sheet one member reads at a time with every view logged, and the packet once they've cleared it. A pass is free and never counted against them.

What does a member see of a job, and when?

Three stages, each opening only when the one before it is done: the teaser, the sheet and the packet. `sees` chooses the fields of the first two:

```bash
grep sees pools/attorneys.ts
```

```txt title="magic values: client.email = signs@example.test, member = mbr_eligible"
  sees: { teaser: ['act', 'region', 'fee_usd', 'signals'], sheet: ['parties', 'kind', 'amount'] },
```

## The teaser

Every offer is a teaser: the `sees.teaser` fields plus the minutes the work takes, the fee per estimated hour and the due date. It never carries a party's name, so it is safe as a push payload, and it is the same in the feed and in the push:

```txt
→ GET /reviews/tsk_7Hq2   # as mbr_eligible
```

```json title="200 · magic values: client.email = signs@example.test, member = mbr_eligible"
{
  "id": "tsk_7Hq2",
  "object": "task",
  "livemode": false,
  "pool": "attorneys",
  "role": "attorney",
  "status": "open",
  "fields": {
    "act": "sign",
    "region": "US-NY",
    "fee_usd": 75,
    "signals": [
      "collections",
      "recipient_elsewhere"
    ]
  },
  "est": {
    "minutes": 30,
    "from": "step"
  },
  "hourly_usd": 150,
  "due": "2026-10-27T14:02:11.000Z",
  "simulated": true
}

# the push payload: the review.offered event a signer receives
{
  "type": "review.offered",
  "data": {
    "task": "tsk_7Hq2",
    "offer": "cascade",
    "teaser": {
      "id": "tsk_7Hq2",
      "object": "task",
      "livemode": false,
      "pool": "attorneys",
      "role": "attorney",
      "status": "open",
      "fields": {
        "act": "sign",
        "region": "US-NY",
        "fee_usd": 75,
        "signals": [
          "collections",
          "recipient_elsewhere"
        ]
      },
      "est": {
        "minutes": 30,
        "from": "step"
      },
      "hourly_usd": 150,
      "due": "2026-10-27T14:02:11.000Z",
      "simulated": true
    }
  }
}

# no party in either: ada lovelace absent · ada@example.com absent · initech absent · ap@initech.example absent
```

- **The minutes are measured.** Once a step has `probation.tasks` accepted acts, `est_minutes` is their median over 30 days, and the rate is the fee over that. Until then it is the step's own `est`, and the teaser says which.
- **In a work register**, the teaser adds the window, the distance from the member's base, and whether travel is paid. The address opens only on the claim.

## The sheet

The sheet adds the `sees.sheet` fields, party names included, and the statements the member attests to clear it. One member reads it at a time, for the Pool's `sheet` span, and every view is logged:

```txt
→ GET /reviews/tsk_7Hq2/sheet   # as mbr_7Hq2, offered it first
```

```json title="200 · magic values: client.email = signs@example.test, member = mbr_eligible"
{
  "id": "tsk_7Hq2",
  "object": "sheet",
  "livemode": false,
  "pool": "attorneys",
  "role": "attorney",
  "status": "open",
  "fields": {
    "act": "sign",
    "region": "US-NY",
    "fee_usd": 75,
    "signals": [
      "collections",
      "recipient_elsewhere"
    ],
    "parties": [
      {
        "as": "client",
        "name": "Ada Lovelace"
      },
      {
        "as": "recipient",
        "name": "Initech",
        "org": "Initech Inc"
      }
    ],
    "kind": "Demand Letter",
    "amount": 4200
  },
  "est": {
    "minutes": 30,
    "from": "step"
  },
  "hourly_usd": 150,
  "due": "2026-10-27T14:02:11.000Z",
  "simulated": true,
  "clear": [
    "I checked conflicts across my full book, including my firm"
  ]
}
```

While one member has it, another is told to wait:

```txt
→ GET /reviews/tsk_7Hq2/sheet   # as mbr_eligible, while mbr_7Hq2 has it
```

```txt title="magic values: client.email = signs@example.test, member = mbr_eligible"
← 409 task_taken: tsk_7Hq2 is offered to other signers first, until 2026-10-25T15:02:11.000Z.
```

Because a sheet names parties, the client consents before the first Task posts, and `check` fails [`sheet_without_consent`](https://services.dev/docs/reference/check/sheet_without_consent.md) on a Service that lets one post first.

## A pass

A pass is free, under [the member charter](https://services.dev/docs/people/pool/door.md#the-member-charter). It is counted against the Task, never against the member, and its `reason` is one word of five. Under `cascade` it moves the Task on at once, and the member who passed isn't offered it again until the fee is raised:

```txt
→ POST /reviews/tsk_7Hq2/pass {"reason":"fee"}   # as mbr_7Hq2
```

```txt title="magic values: client.email = signs@example.test, member = mbr_eligible"
← 200 tsk_7Hq2 · open · attorney · sign · US-NY · $75.00 · signals collections, recipient_elsewhere · 30 min · $150.00 an hour · due 2026-10-27 14:02
```

| `reason` | When a quorum passes for it |
|---|---|
| `fee` | the next raise fires now |
| `scope`, `area` | the next widen fires now |
| `timing` | the due date moves a day |
| `other`, any other word, or none | nothing moves |

The owner reads the views and the passes by reason, never who passed for what:

```txt
→ GET /owner/reviews/tsk_7Hq2   # the owner console
```

```txt title="magic values: client.email = signs@example.test, member = mbr_eligible"
← views [{"member":"mbr_7Hq2","at":"2026-10-25T14:02:11.000Z"}] · passes {"fee":1} · viewers 1 · jump null · offered mbr_7Hq2 (cascade), mbr_eligible (cascade)
```

Once at least `jump.min` members have read the sheet since the last rung, and more than half of them passed for one reason, that reason's [fill rung](https://services.dev/docs/people/pool/fill.md) fires early. Here three members pass on fee, and the raise due at two hours fires at once:

```txt
→ POST /matters {"service":"demand-letter","client":{"name":"Ada Lovelace","email":"signs@example.test"},"recipient":{"name":"Initech","email":"ap@initech.example","org":"Initech Inc"},"claim":"unpaid debt for invoice 1042","amount":4200,"client_region":"US-NY","recipient_region":"US-NJ","evidence":["invoice-1042.pdf"],"max_usd":149,"key":"quorum"}
```

```txt title="magic values: client.email = signs@example.test, member = mbr_eligible"
← job_7Hq2 · waiting · on claim · $149.00 held · sign · tsk_7Hq2

→ GET /reviews/tsk_7Hq2/sheet   # as mbr_7Hq2
← 200 sheet · fee $75.00
→ POST /reviews/tsk_7Hq2/pass {"reason":"fee"}   # as mbr_7Hq2
← 200 tsk_7Hq2 · open · attorney · sign · US-NY · $75.00 · signals collections, recipient_elsewhere · 30 min · $150.00 an hour · due 2026-10-27 14:02
→ GET /reviews/tsk_7Hq2/sheet   # as mbr_7Hq3
← 200 sheet · fee $75.00
→ POST /reviews/tsk_7Hq2/pass {"reason":"fee"}   # as mbr_7Hq3
← 200 tsk_7Hq2 · open · attorney · sign · US-NY · $75.00 · signals collections, recipient_elsewhere · 30 min · $150.00 an hour · due 2026-10-27 14:02
→ GET /reviews/tsk_7Hq2/sheet   # as mbr_7Hq4
← 200 sheet · fee $75.00
→ POST /reviews/tsk_7Hq2/pass {"reason":"fee"}   # as mbr_7Hq4
← 200 tsk_7Hq2 · open · attorney · sign · US-NY · $82.50 · signals collections, recipient_elsewhere · 30 min · $165.00 an hour · due 2026-10-27 14:02

→ GET /owner/reviews/tsk_7Hq2   # the owner console
← passes {"fee":3} · viewers 3 · posted $75.00, now $82.50
  fired  raise 10% 2h · 14:02 · raised to $82.50 · jumped
```

## Clearance, then the packet

To clear a claimed Task, the member attests each `clear` statement, word for word. That is the seventh predicate of [eligibility](https://services.dev/docs/people/pool/eligibility.md), and the conflict check runs again with it. Then [the packet](https://services.dev/docs/people/pool/packet.md) opens, to that member alone.

## Keys

| Key | Written | Left out | Does |
|---|---|---|---|
| `sees` | `{ teaser: string[]; sheet?: string[] }` | &#123; teaser: [`'act'`, `'region'`, `'fee_usd'`] &#125; | What a member sees: the teaser before claiming (always with est_minutes, measured or estimated, the rate and the due date, never a party name), and the sheet. |
| `clear` | `string[] \| { attest: string[]; check?: string[] }` | none | What a member attests before the packet opens, and the party inputs checked, hashed, against their ledger. |
| `sheet` | `ShortSpan` | `'10min'` | How long one member has a sheet to themselves. |
| `jump` | `{ min?: number }` | &#123; min: 3 &#125; | When passes move the ladder: at least `min` distinct sheet viewers since the last rung, and more than half of them passing for the same kind of reason. |
| `contact` | `'thread'` | `'thread'` | Member contact with a party relays through the job's thread, the only value: email and phone never cross either way. |

Worked in: [the closers' feed](https://services.dev/docs/examples/sales/delivery-portal.md#2-read-the-feed), a teaser before the claim.

---

- Up: [Pool(): your marketplace](https://services.dev/docs/people/pool.md)
- Previous: [Conflicts without disclosure](https://services.dev/docs/people/pool/conflicts.md)
- Next: [The packet](https://services.dev/docs/people/pool/packet.md)
