org.cannadb.plant
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.
Details · record, key tid
| Kind | record |
|---|---|
| Record key | tid |
| Authority | cannadb.org |
| Indexed |
Checks
Validlarge-stringdefs.harvest.properties.notesmaxLength is over 20 KB. Use a blob for content that large.unlimited-stringdefs.main.record.properties.parentPlantNameNo maxLength, maxGraphemes or format limits this string.unlimited-stringdefs.main.record.properties.strainNameNo maxLength, maxGraphemes or format limits this string.
{
"$type": "com.atproto.lexicon.schema",
"defs": {
"harvest": {
"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.",
"properties": {
"dryWeightG": {
"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.",
"minimum": 0,
"type": "integer"
},
"floweringDays": {
"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.",
"maximum": 365,
"minimum": 0,
"type": "integer"
},
"harvestedAt": {
"description": "When the plant was harvested (cut down).",
"format": "datetime",
"type": "string"
},
"measuredCbd": {
"description": "Lab-tested CBD percentage in hundredths of a percent, if available.",
"maximum": 10000,
"minimum": 0,
"type": "integer"
},
"measuredThc": {
"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`.",
"maximum": 10000,
"minimum": 0,
"type": "integer"
},
"notes": {
"description": "Markdown-formatted free-form harvest notes — trim/dry/cure method, smell, observations.",
"maxGraphemes": 5000,
"maxLength": 50000,
"type": "string"
},
"wetWeightG": {
"description": "Wet (fresh-cut) weight in hundredths of a gram (e.g., 50000 = 500.00 g).",
"minimum": 0,
"type": "integer"
}
},
"type": "object"
},
"main": {
"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.",
"key": "tid",
"record": {
"properties": {
"createdAt": {
"description": "Client-declared timestamp when this plant record was originally created.",
"format": "datetime",
"type": "string"
},
"grow": {
"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.)",
"format": "at-uri",
"type": "string"
},
"harvest": {
"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.",
"ref": "#harvest",
"type": "ref"
},
"isClone": {
"description": "Whether this plant is a clone (cut) rather than grown from seed. When true, `parentPlant` may reference the plant it was cut from.",
"type": "boolean"
},
"label": {
"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,
"maxLength": 2000,
"type": "string"
},
"parentPlant": {
"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.)",
"format": "at-uri",
"type": "string"
},
"parentPlantName": {
"description": "Display fallback for the parent plant when `parentPlant` is absent or unresolved.",
"type": "string"
},
"startedAt": {
"description": "When this plant's life began for the grower (germination or the date the clone/seed was planted). Optional.",
"format": "datetime",
"type": "string"
},
"strain": {
"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.)",
"format": "at-uri",
"type": "string"
},
"strainName": {
"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.",
"type": "string"
}
},
"required": [
"grow",
"createdAt"
],
"type": "object"
},
"type": "record"
}
},
"id": "org.cannadb.plant",
"lexicon": 1
}