# org.cannadb.strainEdit

> 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.strainEdit)
- [Documentation](https://lexicon.garden/lexicon/did:plc:lrtzzib3ycggsodkfidzuorw/org.cannadb.strainEdit/docs)
- [Examples](https://lexicon.garden/lexicon/did:plc:lrtzzib3ycggsodkfidzuorw/org.cannadb.strainEdit/examples)

## Definitions

### `org.cannadb.strainEdit`

**Type**: `record`

A field-level edit to a strain's living document (collaborative editing). Targets a strain via `subject` (the anchor record of the entity) and carries a sparse patch: scalar field overwrites in `set`, additive ops on open array fields in `add`/`remove`, and field clears in `unset`. The AppView folds accepted edits over the anchor record to materialize the canonical document; this record is one signed contribution, attributed to its publisher DID. See docs/05-collaborative-strains.md.

**Key**: `tid`

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `add` | `ref` → `#arrayFields` | No | Values to add to open array fields (union at fold time). |
| `set` | `ref` → `#scalarFields` | No | Scalar and object-valued fields to overwrite (last-writer-wins per field at fold time). |
| `unset` | `array` | No | Field names to clear. Each must be an editable field of org.cannadb.strain. |
| `remove` | `ref` → `#arrayFields` | No | Values to remove from open array fields (set-difference at fold time). |
| `basedOn` | `string` | No | Materialized revision hash this edit was authored against, for conflict detection. Optional; absent for blind edits. |
| `subject` | `string` (at-uri) | Yes | AT-URI of the org.cannadb.strain record anchoring the entity this edit targets. |
| `summary` | `string` | No | Short human edit summary (the commit message). Capped at 200 graphemes (2000 bytes). |
| `createdAt` | `string` (datetime) | Yes | Client-declared timestamp when this edit was created. Also the fold ordering key (ties broken by record URI). |

### `org.cannadb.strainEdit#arrayFields`

**Type**: `object`

Open array fields that support additive add/remove merge. Lineage arrays (parents/versionOf and their parallel name arrays) are NOT here — they are replaced wholesale via `set` because their parallel-index structure does not merge element-wise.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `effects` | `array` | No |  |
| `flavors` | `array` | No |  |
| `terpenes` | `array` | No |  |
| `alsoKnownAs` | `array` | No |  |
| `characteristics` | `array` | No |  |
| `medicinalEffects` | `array` | No |  |
| `seedAvailability` | `array` | No |  |

### `org.cannadb.strainEdit#scalarFields`

**Type**: `object`

The strain's scalar and object-valued fields, all optional. Mirrors org.cannadb.strain. Range/yield objects reference the same shapes the strain lexicon defines. Identity fields (name, kind, breeder, holder) are expressible here; whether such an edit is accepted is an AppView fold/governance concern, not a lexicon constraint.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `kind` | `string` | No |  |
| `name` | `string` | No |  |
| `yield` | `ref` → `org.cannadb.strain#yieldRange` | No |  |
| `height` | `ref` → `org.cannadb.strain#heightRange` | No |  |
| `holder` | `string` (at-uri) | No |  |
| `breeder` | `string` (at-uri) | No |  |
| `parents` | `array` | No |  |
| `cbdRange` | `ref` → `org.cannadb.strain#cannabinoidRange` | No |  |
| `thcRange` | `ref` → `org.cannadb.strain#cannabinoidRange` | No |  |
| `cycleTime` | `ref` → `org.cannadb.strain#dayRange` | No |  |
| `sourceUrl` | `string` (uri) | No |  |
| `versionOf` | `array` | No |  |
| `autoflower` | `boolean` | No |  |
| `generation` | `string` | No |  |
| `holderName` | `string` | No |  |
| `originYear` | `integer` | No |  |
| `breederName` | `string` | No |  |
| `cbdDominant` | `boolean` | No |  |
| `description` | `string` | No |  |
| `growthOdour` | `string` | No |  |
| `parentNames` | `array` | No |  |
| `thcCbdRatio` | `string` | No |  |
| `indicaSativa` | `integer` | No |  |
| `originRegion` | `string` | No |  |
| `growDifficulty` | `string` | No |  |
| `versionOfNames` | `array` | No |  |
| `cultivationNotes` | `string` | No |  |
| `shortDescription` | `string` | No |  |
| `parentBreederNames` | `array` | No |  |

## Raw Schema

```json
{
  "id": "org.cannadb.strainEdit",
  "defs": {
    "main": {
      "key": "tid",
      "type": "record",
      "record": {
        "type": "object",
        "required": [
          "subject",
          "createdAt"
        ],
        "properties": {
          "add": {
            "ref": "#arrayFields",
            "type": "ref",
            "description": "Values to add to open array fields (union at fold time)."
          },
          "set": {
            "ref": "#scalarFields",
            "type": "ref",
            "description": "Scalar and object-valued fields to overwrite (last-writer-wins per field at fold time)."
          },
          "unset": {
            "type": "array",
            "items": {
              "type": "string",
              "description": "An editable strain field name to clear, e.g., \"growthOdour\"."
            },
            "description": "Field names to clear. Each must be an editable field of org.cannadb.strain."
          },
          "remove": {
            "ref": "#arrayFields",
            "type": "ref",
            "description": "Values to remove from open array fields (set-difference at fold time)."
          },
          "basedOn": {
            "type": "string",
            "description": "Materialized revision hash this edit was authored against, for conflict detection. Optional; absent for blind edits."
          },
          "subject": {
            "type": "string",
            "format": "at-uri",
            "description": "AT-URI of the org.cannadb.strain record anchoring the entity this edit targets."
          },
          "summary": {
            "type": "string",
            "maxLength": 2000,
            "description": "Short human edit summary (the commit message). Capped at 200 graphemes (2000 bytes).",
            "maxGraphemes": 200
          },
          "createdAt": {
            "type": "string",
            "format": "datetime",
            "description": "Client-declared timestamp when this edit was created. Also the fold ordering key (ties broken by record URI)."
          }
        }
      },
      "description": "A field-level edit to a strain's living document (collaborative editing). Targets a strain via `subject` (the anchor record of the entity) and carries a sparse patch: scalar field overwrites in `set`, additive ops on open array fields in `add`/`remove`, and field clears in `unset`. The AppView folds accepted edits over the anchor record to materialize the canonical document; this record is one signed contribution, attributed to its publisher DID. See docs/05-collaborative-strains.md."
    },
    "arrayFields": {
      "type": "object",
      "properties": {
        "effects": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "flavors": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "terpenes": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "alsoKnownAs": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "characteristics": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "medicinalEffects": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "seedAvailability": {
          "type": "array",
          "items": {
            "type": "string",
            "knownValues": [
              "regular",
              "feminized",
              "autoflower",
              "clone_only"
            ]
          }
        }
      },
      "description": "Open array fields that support additive add/remove merge. Lineage arrays (parents/versionOf and their parallel name arrays) are NOT here — they are replaced wholesale via `set` because their parallel-index structure does not merge element-wise."
    },
    "scalarFields": {
      "type": "object",
      "properties": {
        "kind": {
          "type": "string",
          "knownValues": [
            "strain",
            "cut"
          ]
        },
        "name": {
          "type": "string"
        },
        "yield": {
          "ref": "org.cannadb.strain#yieldRange",
          "type": "ref"
        },
        "height": {
          "ref": "org.cannadb.strain#heightRange",
          "type": "ref"
        },
        "holder": {
          "type": "string",
          "format": "at-uri"
        },
        "breeder": {
          "type": "string",
          "format": "at-uri"
        },
        "parents": {
          "type": "array",
          "items": {
            "type": "string",
            "format": "at-uri"
          }
        },
        "cbdRange": {
          "ref": "org.cannadb.strain#cannabinoidRange",
          "type": "ref"
        },
        "thcRange": {
          "ref": "org.cannadb.strain#cannabinoidRange",
          "type": "ref"
        },
        "cycleTime": {
          "ref": "org.cannadb.strain#dayRange",
          "type": "ref"
        },
        "sourceUrl": {
          "type": "string",
          "format": "uri"
        },
        "versionOf": {
          "type": "array",
          "items": {
            "type": "string",
            "format": "at-uri"
          }
        },
        "autoflower": {
          "type": "boolean"
        },
        "generation": {
          "type": "string"
        },
        "holderName": {
          "type": "string"
        },
        "originYear": {
          "type": "integer"
        },
        "breederName": {
          "type": "string"
        },
        "cbdDominant": {
          "type": "boolean"
        },
        "description": {
          "type": "string"
        },
        "growthOdour": {
          "type": "string",
          "knownValues": [
            "low",
            "medium",
            "high"
          ]
        },
        "parentNames": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "thcCbdRatio": {
          "type": "string"
        },
        "indicaSativa": {
          "type": "integer",
          "maximum": 100,
          "minimum": 0
        },
        "originRegion": {
          "type": "string"
        },
        "growDifficulty": {
          "type": "string",
          "knownValues": [
            "easy",
            "intermediate",
            "hard"
          ]
        },
        "versionOfNames": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "cultivationNotes": {
          "type": "string"
        },
        "shortDescription": {
          "type": "string"
        },
        "parentBreederNames": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "description": "The strain's scalar and object-valued fields, all optional. Mirrors org.cannadb.strain. Range/yield objects reference the same shapes the strain lexicon defines. Identity fields (name, kind, breeder, holder) are expressible here; whether such an edit is accepted is an AppView fold/governance concern, not a lexicon constraint."
    }
  },
  "$type": "com.atproto.lexicon.schema",
  "lexicon": 1
}
```
