at.happyproto.plugin.profile

happyproto.at

Samples

1 randomly sampled records from the AT Protocol firehose

at.happyproto.plugin.profile (1 sample)
{
  "$type": "at.happyproto.plugin.profile",
  "authors": [
    {
      "email": "tre@trezy.com",
      "name": "Trezy"
    }
  ],
  "description": "Record writes as the calling user, local index writes, and lexicon validation.",
  "keywords": [
    "happyview",
    "records",
    "lexicon",
    "atproto",
    "library"
  ],
  "lastUpdated": "2026-10-20T03:03:34Z",
  "license": "MIT",
  "name": "Record",
  "sections": {
    "changelog": "## [1.0.0](https://github.com/happyproto/plugins/releases/tag/happyview-record-v1.0.0) (2026-10-07)\n\n- **First release, on HappyView v3's plugin API.** Scripts get `happyview.record`: `create`, `put`, `delete` and `upload_blob` as the calling user, `load` for indexed records, `save_local` and `delete_local` for writing the local index directly, and `validate` and `lexicon` for checking records against the lexicons your instance holds.\n- **Your own writes show up right away.** `create`, `put` and `delete` mirror into the local index as soon as the PDS accepts them, so the next `load` sees them without waiting for the network to echo the record back.\n",
    "description": "`happyview.record` is how a script writes records. It writes to the calling user's repo on their PDS, writes directly to your instance's local index, and checks records against the lexicons your instance holds.\n\n## Usage\n\n```lua\nlocal record = require(\"happyview.record\")\n\nfunction handle(input, ctx)\n  local ref = record.create(\"app.bsky.feed.post\", {text = input.text})\n  local saved = record.load(ref.uri)   -- already there, see below\n  return {uri = ref.uri, cid = saved.cid}\nend\n```\n\nYou see your own writes right away. `create`, `put` and `delete` mirror into the local index as soon as the PDS accepts them, so the next `load` (or any `happyview.db` read) has them. `indexed_at` stays nil until the network echoes the record back.\n\n## API\n\n- `create(collection, tbl[, opts])` and `put(uri, tbl[, opts])` return `{uri, cid}`. `put` takes `opts.swap_cid` and refuses the write unless it matches the current CID.\n- `delete(uri)` deletes from the user's repo, and `upload_blob(bytes, mime_type)` returns the PDS's blob ref.\n- `load(uri)` returns `{uri, did, collection, rkey, cid, indexed_at, record}`, or nil.\n- `save_local(collection, rkey, tbl[, did])` and `delete_local(uri)` skip the PDS and write the index directly. They also work in label and record-event scripts, which have no user to act as (pass `save_local` a `did` there).\n- `validate(collection, tbl)` normalizes and checks a record without writing it.\n- `lexicon(collection)` returns the stored lexicon document, or nil.\n\nEvery write fills in `$type` and the lexicon's declared defaults. Required fields are checked unless you pass `validate = false` to `create` or `put`.\n\nThere's no `generate_rkey`. Use `require(\"internal.tids\").create()`.\n\n## Capabilities\n\n- `caller:write`, to write to the calling user's own repo.\n- `records:write`, to write into the local index.\n- `records:read`, for `load` and `lexicon`.\n\nTwo of those write data, so it's High tier.\n",
    "installation": "You need HappyView v3 (plugin `api_version` `\"2\"`). This is a library plugin, so it does nothing on its own: scripts call it, and a script only runs when an interpreter plugin is installed (`happyview-lua`, `happyview-javascript` or `happyview-typescript`).\n\n## Install\n\nThe whole install is one manifest URL. HappyView fetches the `.wasm` from beside it.\n\n```\nhttps://github.com/happyproto/plugins/releases/download/happyview-record-v1.0.0/manifest.json\n```\n\nThat's the current release. Newer ones show up on the [releases page](https://github.com/happyproto/plugins/releases), tagged `happyview-record-v<version>`.\n\nPick one route:\n\n1. **Dashboard.** Go to **Settings > Plugins**, click **Add Plugin**, paste the URL, review the details and click **Install Plugin**.\n2. **Environment.** Set `PLUGIN_URLS` before HappyView starts:\n\n   ```\n   PLUGIN_URLS=happyview-record|https://github.com/happyproto/plugins/releases/download/happyview-record-v1.0.0/manifest.json\n   ```\n\n   The format is `id|url`, or `id|url|sha256:<hash>` to pin the download. Separate several plugins with commas.\n3. **File system.** Put the release's `manifest.json` and `happyview-record.wasm` in a directory under `./plugins/`, such as `./plugins/record/`.\n\n## Configuration\n\nNone. It needs no secrets and no allowed hosts. Lexicon defaults and required-field checks come from the lexicons this instance already holds, so a collection with no lexicon uploaded gets neither (it still gets its `$type`).\n\n## Check it worked\n\nThe plugin is listed on **Settings > Plugins**, and `require(\"happyview.record\")` succeeds in a Lua script. If you installed through `PLUGIN_URLS` or the file system and it's missing, look in the boot log for `Failed to install plugin at boot`. HappyView logs a refused plugin there and starts without it.\n",
    "security": "## Reporting a vulnerability\n\nReport it privately through GitHub's [advisory form](https://github.com/happyproto/plugins/security/advisories/new). Please don't open a public issue for a vulnerability.\n\nOnly the latest release of `happyview-record` gets fixes, so check you're on it first.\n\n## What this plugin can reach\n\nIt declares `caller:write`, `records:read` and `records:write`, and the repo README puts it in the High tier, because two of those write data:\n\n- **`caller:write`** writes to the calling user's own repo on their PDS (`create`, `put`, `delete`, `upload_blob`). The host owns the session; the plugin never sees credentials.\n- **`records:write`** writes directly to this instance's index, skipping the PDS (`save_local`, `delete_local`). `save_local` takes an optional `did` and passes it to the host as given, so it isn't limited to the caller's repo.\n\n`records:read` covers `load` and `lexicon`. The plugin imports exactly eight host functions, all listed in its README. Like every HappyView plugin, it runs sandboxed in WASM with no filesystem access, and the loader refuses a module whose imports need more than its manifest declares.\n\n## What's worth reporting\n\n- A caller-acting write landing in a repo that isn't the caller's, or running with no caller at all instead of failing with `NO_SESSION`.\n- `put` with `swap_cid` replacing a record whose CID doesn't match.\n- Required-field validation being skipped when `validate` wasn't set to `false`.\n- Anything that lets a script write into the index outside what `save_local` and `delete_local` describe.\n"
  },
  "security": [
    {
      "url": "https://github.com/happyproto/plugins/security/advisories/new"
    }
  ],
  "type": "happyview-plugin"
}

did:plc:mo7vq4jbioxwafy5zkcc3eux | at://did:plc:mo7vq4jbioxwafy5zkcc3eux/at.happyproto.plugin.profile/happyview-record

Lexicon Garden

@