blue.hearth.entitlement

hearth.blue

Documentation

Proof that a subscriber currently holds a tier. This is the record attested.network deliberately leaves undefined: its payment records prove a payment happened but carry no expiry, revocation or status, so they cannot answer 'is this subscription active right now'. Lives in the SUBSCRIBER's repository, alongside the payment record that granted it. Entitlements are short-lived and RENEWED, never long-lived and revoked: each successful billing cycle writes a fresh record, so cancellation is the observable absence of a renewal rather than a revocation list a verifier must fetch and trust.

main record

Proof that a subscriber currently holds a tier. This is the record attested.network deliberately leaves undefined: its payment records prove a payment happened but carry no expiry, revocation or status, so they cannot answer 'is this subscription active right now'. Lives in the SUBSCRIBER's repository, alongside the payment record that granted it. Entitlements are short-lived and RENEWED, never long-lived and revoked: each successful billing cycle writes a fresh record, so cancellation is the observable absence of a renewal rather than a revocation list a verifier must fetch and trust.

Record Key tid Timestamp-based ID

Properties

createdAt string datetime Required

An RFC 3339 formatted timestamp.

creator string did Required

The creator this entitlement is for. Derivable from tier's AT-URI, but stated explicitly so a verifier answering 'does X subscribe to Y' can filter without dereferencing every tier record.

payment ref com.atproto.repo.strongRef Required

The network.attested.payment.recurring record that granted this. Normally in the same repository, since both the payment record and the entitlement live with the subscriber.

signatures array of unknown Optional

badge.blue attestations over this record: the creator's proof and the broker's. Left as unknown because badge.blue defines both the inline (ECDSA in-record) and remote (strongRef to a proof record) shapes, and pinning either here would break the other. An entitlement with no signatures is worthless to a verifier and must not be trusted.

status string Required

active is the normal case and the only one written on renewal. cancelled is optional and terminal, written when a subscriber cancels, so propagation is immediate rather than waiting out validUntil. lapsed marks a known payment failure. A verifier must still check validUntil against the current time: status alone is never sufficient, since an active record whose window has passed is expired. Closed rather than knownValues on purpose — an un-enumerated status is exactly the defect in the spec this record exists to fix, and a verifier that meets a status it does not know cannot safely decide either way, so such a record should fail validation rather than reach the verifier at all. The cost is real: adding a value later (say paused) is a lexicon revision that older validators will reject.

Allowed: active, cancelled, lapsed
tier ref com.atproto.repo.strongRef Required

The blue.hearth.tier record granted. A strongRef, so the tier's terms at grant time are pinned by CID and cannot be edited out from under an existing entitlement.

validFrom string datetime Required

An RFC 3339 formatted timestamp.

validUntil string datetime Required

End of the billing period PLUS a grace window. The grace exists because recurring payments bill on anniversary dates with automatic retry: without slack, a card merely awaiting retry reads as lapsed to every independent verifier, and hearth could not correct that, because verifiers do not call hearth.

View raw schema
{
  "key": "tid",
  "type": "record",
  "record": {
    "type": "object",
    "required": [
      "creator",
      "tier",
      "payment",
      "validFrom",
      "validUntil",
      "status",
      "createdAt"
    ],
    "properties": {
      "tier": {
        "ref": "com.atproto.repo.strongRef",
        "type": "ref",
        "description": "The blue.hearth.tier record granted. A strongRef, so the tier's terms at grant time are pinned by CID and cannot be edited out from under an existing entitlement."
      },
      "status": {
        "enum": [
          "active",
          "cancelled",
          "lapsed"
        ],
        "type": "string",
        "description": "active is the normal case and the only one written on renewal. cancelled is optional and terminal, written when a subscriber cancels, so propagation is immediate rather than waiting out validUntil. lapsed marks a known payment failure. A verifier must still check validUntil against the current time: status alone is never sufficient, since an active record whose window has passed is expired. Closed rather than knownValues on purpose — an un-enumerated status is exactly the defect in the spec this record exists to fix, and a verifier that meets a status it does not know cannot safely decide either way, so such a record should fail validation rather than reach the verifier at all. The cost is real: adding a value later (say paused) is a lexicon revision that older validators will reject."
      },
      "creator": {
        "type": "string",
        "format": "did",
        "description": "The creator this entitlement is for. Derivable from tier's AT-URI, but stated explicitly so a verifier answering 'does X subscribe to Y' can filter without dereferencing every tier record."
      },
      "payment": {
        "ref": "com.atproto.repo.strongRef",
        "type": "ref",
        "description": "The network.attested.payment.recurring record that granted this. Normally in the same repository, since both the payment record and the entitlement live with the subscriber."
      },
      "createdAt": {
        "type": "string",
        "format": "datetime"
      },
      "validFrom": {
        "type": "string",
        "format": "datetime"
      },
      "signatures": {
        "type": "array",
        "items": {
          "type": "unknown"
        },
        "description": "badge.blue attestations over this record: the creator's proof and the broker's. Left as unknown because badge.blue defines both the inline (ECDSA in-record) and remote (strongRef to a proof record) shapes, and pinning either here would break the other. An entitlement with no signatures is worthless to a verifier and must not be trusted."
      },
      "validUntil": {
        "type": "string",
        "format": "datetime",
        "description": "End of the billing period PLUS a grace window. The grace exists because recurring payments bill on anniversary dates with automatic retry: without slack, a card merely awaiting retry reads as lapsed to every independent verifier, and hearth could not correct that, because verifiers do not call hearth."
      }
    }
  },
  "description": "Proof that a subscriber currently holds a tier. This is the record attested.network deliberately leaves undefined: its payment records prove a payment happened but carry no expiry, revocation or status, so they cannot answer 'is this subscription active right now'. Lives in the SUBSCRIBER's repository, alongside the payment record that granted it. Entitlements are short-lived and RENEWED, never long-lived and revoked: each successful billing cycle writes a fresh record, so cancellation is the observable absence of a renewal rather than a revocation list a verifier must fetch and trust."
}

Lexicon Garden

@