# org.cannadb.plant

> Published by [cannadb.org](https://lexicon.garden/identity/did:plc:lrtzzib3ycggsodkfidzuorw)

✓ This is the authoritative definition for this NSID.

## Links

- [View on Lexicon Garden](https://lexicon.garden/lexicon/did:plc:lrtzzib3ycggsodkfidzuorw/org.cannadb.plant)
- [Documentation](https://lexicon.garden/lexicon/did:plc:lrtzzib3ycggsodkfidzuorw/org.cannadb.plant/docs)
- [Examples](https://lexicon.garden/lexicon/did:plc:lrtzzib3ycggsodkfidzuorw/org.cannadb.plant/examples)

## Definitions

### `org.cannadb.plant`

**Type**: `record`

A single plant within a grow. The plant is the lifecycle unit: it references the `org.cannadb.grow` it belongs to and (optionally) the `org.cannadb.strain` it is. Its lifecycle stage is NOT stored as a mutable field here — stage transitions are append-only `org.cannadb.growEntry` events (kind "stage"), and the AppView computes the current stage from the latest such event. Measured harvest outcomes, once known, are recorded in the optional `harvest` object so the AppView can aggregate real cultivation data across many grows of the same strain ("growers' average flowering time / yield"). Publishing this record IS the claim — every field is contextualized by the publisher DID at display time.

**Key**: `tid`

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `grow` | `string` (at-uri) | Yes | AT-URI reference to the `org.cannadb.grow` this plant belongs to. The grow is expected to be published by the same DID. (The lexicon spec does not enforce collection constraints on at-uri; consumers should validate the ref resolves to an `org.cannadb.grow` record.) |
| `label` | `string` | No | Short label distinguishing this plant within the grow, e.g., "WC #1". Optional — the AppView falls back to the strain name plus an index. |
| `strain` | `string` (at-uri) | No | AT-URI reference to the `org.cannadb.strain` record (any `kind`) this plant is a grow of. Canonical when present and resolvable; `strainName` is the display fallback. This is the seam to the strain library — the same ref that an Isley import keys on. (The lexicon spec does not enforce collection constraints on at-uri; consumers should validate the ref resolves to an `org.cannadb.strain` record.) |
| `harvest` | `ref` → `#harvest` | No | Measured harvest outcomes for this plant, recorded once the run completes. Optional and entirely additive — a plant in veg has no harvest object. The AppView aggregates these across grows of the same strain. |
| `isClone` | `boolean` | No | Whether this plant is a clone (cut) rather than grown from seed. When true, `parentPlant` may reference the plant it was cut from. |
| `createdAt` | `string` (datetime) | Yes | Client-declared timestamp when this plant record was originally created. |
| `startedAt` | `string` (datetime) | No | When this plant's life began for the grower (germination or the date the clone/seed was planted). Optional. |
| `strainName` | `string` | No | Display fallback for the strain name. Used when no `strain` ref is available, when the ref does not resolve, or for bag-seed / unknown genetics with no atproto presence. |
| `parentPlant` | `string` (at-uri) | No | For clones: AT-URI reference to the `org.cannadb.plant` this plant was cut from. `parentPlantName` is the display fallback. (Consumers should validate the ref resolves to an `org.cannadb.plant` record.) |
| `parentPlantName` | `string` | No | Display fallback for the parent plant when `parentPlant` is absent or unresolved. |

### `org.cannadb.plant#harvest`

**Type**: `object`

Measured outcomes of a completed plant. All fields optional. Decimal quantities use the scaled-integer convention from `org.cannadb.strain` (atproto has no float type): weights are in hundredths of a gram, cannabinoid percentages in hundredths of a percent.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `notes` | `string` | No | Markdown-formatted free-form harvest notes — trim/dry/cure method, smell, observations. |
| `dryWeightG` | `integer` | No | Final dry/cured weight in hundredths of a gram (e.g., 12500 = 125.00 g). This is the figure the AppView aggregates into per-strain yield rails. |
| `wetWeightG` | `integer` | No | Wet (fresh-cut) weight in hundredths of a gram (e.g., 50000 = 500.00 g). |
| `harvestedAt` | `string` (datetime) | No | When the plant was harvested (cut down). |
| `measuredCbd` | `integer` | No | Lab-tested CBD percentage in hundredths of a percent, if available. |
| `measuredThc` | `integer` | No | Lab-tested THC percentage in hundredths of a percent (e.g., 2450 = 24.50%), if available. Distinct from the strain record's breeder-claimed `thcRange`. |
| `floweringDays` | `integer` | No | Actual flowering duration in days (start of 12/12 — or, for autoflowers, the full run — to harvest). The AppView aggregates this into a growers' average flowering time alongside the breeder-claimed `cycleTime` range on the strain. |

## Raw Schema

```json
{
  "id": "org.cannadb.plant",
  "defs": {
    "main": {
      "key": "tid",
      "type": "record",
      "record": {
        "type": "object",
        "required": [
          "grow",
          "createdAt"
        ],
        "properties": {
          "grow": {
            "type": "string",
            "format": "at-uri",
            "description": "AT-URI reference to the `org.cannadb.grow` this plant belongs to. The grow is expected to be published by the same DID. (The lexicon spec does not enforce collection constraints on at-uri; consumers should validate the ref resolves to an `org.cannadb.grow` record.)"
          },
          "label": {
            "type": "string",
            "maxLength": 2000,
            "description": "Short label distinguishing this plant within the grow, e.g., \"WC #1\". Optional — the AppView falls back to the strain name plus an index.",
            "maxGraphemes": 200
          },
          "strain": {
            "type": "string",
            "format": "at-uri",
            "description": "AT-URI reference to the `org.cannadb.strain` record (any `kind`) this plant is a grow of. Canonical when present and resolvable; `strainName` is the display fallback. This is the seam to the strain library — the same ref that an Isley import keys on. (The lexicon spec does not enforce collection constraints on at-uri; consumers should validate the ref resolves to an `org.cannadb.strain` record.)"
          },
          "harvest": {
            "ref": "#harvest",
            "type": "ref",
            "description": "Measured harvest outcomes for this plant, recorded once the run completes. Optional and entirely additive — a plant in veg has no harvest object. The AppView aggregates these across grows of the same strain."
          },
          "isClone": {
            "type": "boolean",
            "description": "Whether this plant is a clone (cut) rather than grown from seed. When true, `parentPlant` may reference the plant it was cut from."
          },
          "createdAt": {
            "type": "string",
            "format": "datetime",
            "description": "Client-declared timestamp when this plant record was originally created."
          },
          "startedAt": {
            "type": "string",
            "format": "datetime",
            "description": "When this plant's life began for the grower (germination or the date the clone/seed was planted). Optional."
          },
          "strainName": {
            "type": "string",
            "description": "Display fallback for the strain name. Used when no `strain` ref is available, when the ref does not resolve, or for bag-seed / unknown genetics with no atproto presence."
          },
          "parentPlant": {
            "type": "string",
            "format": "at-uri",
            "description": "For clones: AT-URI reference to the `org.cannadb.plant` this plant was cut from. `parentPlantName` is the display fallback. (Consumers should validate the ref resolves to an `org.cannadb.plant` record.)"
          },
          "parentPlantName": {
            "type": "string",
            "description": "Display fallback for the parent plant when `parentPlant` is absent or unresolved."
          }
        }
      },
      "description": "A single plant within a grow. The plant is the lifecycle unit: it references the `org.cannadb.grow` it belongs to and (optionally) the `org.cannadb.strain` it is. Its lifecycle stage is NOT stored as a mutable field here — stage transitions are append-only `org.cannadb.growEntry` events (kind \"stage\"), and the AppView computes the current stage from the latest such event. Measured harvest outcomes, once known, are recorded in the optional `harvest` object so the AppView can aggregate real cultivation data across many grows of the same strain (\"growers' average flowering time / yield\"). Publishing this record IS the claim — every field is contextualized by the publisher DID at display time."
    },
    "harvest": {
      "type": "object",
      "properties": {
        "notes": {
          "type": "string",
          "maxLength": 50000,
          "description": "Markdown-formatted free-form harvest notes — trim/dry/cure method, smell, observations.",
          "maxGraphemes": 5000
        },
        "dryWeightG": {
          "type": "integer",
          "minimum": 0,
          "description": "Final dry/cured weight in hundredths of a gram (e.g., 12500 = 125.00 g). This is the figure the AppView aggregates into per-strain yield rails."
        },
        "wetWeightG": {
          "type": "integer",
          "minimum": 0,
          "description": "Wet (fresh-cut) weight in hundredths of a gram (e.g., 50000 = 500.00 g)."
        },
        "harvestedAt": {
          "type": "string",
          "format": "datetime",
          "description": "When the plant was harvested (cut down)."
        },
        "measuredCbd": {
          "type": "integer",
          "maximum": 10000,
          "minimum": 0,
          "description": "Lab-tested CBD percentage in hundredths of a percent, if available."
        },
        "measuredThc": {
          "type": "integer",
          "maximum": 10000,
          "minimum": 0,
          "description": "Lab-tested THC percentage in hundredths of a percent (e.g., 2450 = 24.50%), if available. Distinct from the strain record's breeder-claimed `thcRange`."
        },
        "floweringDays": {
          "type": "integer",
          "maximum": 365,
          "minimum": 0,
          "description": "Actual flowering duration in days (start of 12/12 — or, for autoflowers, the full run — to harvest). The AppView aggregates this into a growers' average flowering time alongside the breeder-claimed `cycleTime` range on the strain."
        }
      },
      "description": "Measured outcomes of a completed plant. All fields optional. Decimal quantities use the scaled-integer convention from `org.cannadb.strain` (atproto has no float type): weights are in hundredths of a gram, cannabinoid percentages in hundredths of a percent."
    }
  },
  "$type": "com.atproto.lexicon.schema",
  "lexicon": 1
}
```
