[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6NNMB2BYCM9J8GVW3TJ8YA7":3,"skill-same:01M6NNMB2BYCM9J8GVW3TJ8YA7":74},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":22,"publishedAt":43,"linkOnly":44,"markdownContent":45,"markdownBody":46,"frontMatter":47,"refName":53,"commitSha":54,"skillDirectory":55,"forksCount":56,"repositoryHtmlUrl":57,"repositoryHomepageUrl":6,"ownerHtmlUrl":58,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":59,"install":60,"resources":73},"01M6NNMB2BYCM9J8GVW3TJ8YA7","yjs-collaboration",null,"Yjs CRDT collaboration patterns for real-time and offline-first editing. Use when building collaborative documents, shared scratchpads, or multi-user editing. Covers Y.Doc, Y.Map, Y.Array, Y.Text, state encoding, structured patches, server-side document manipulation, and conflict-free merge semantics.","revealui-studio\u002Frevskills","revealui-studio","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F338824821?v=4","01M6NNBRBPN7P6MK70FZQZ5RAQ","01M6NNBRG527YFDFHNYKTCDA4Y",2,"MIT","https:\u002F\u002Fgithub.com\u002Frevealui-studio\u002Frevskills\u002Fblob\u002Ftest\u002Fskills\u002Fyjs-collaboration\u002FSKILL.md",[17],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000010","后端与接口","SCENARIO","使用场景",[23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42],"yjs collaboration","collaboration","yjs","map","for","studio","free","server-side","conflict","shared","time","merge","patterns","read","text","doc","real-time","server","offline","documents","2026-11-10 10:12:30",false,"---\nname: yjs-collaboration\ndescription: Yjs CRDT collaboration patterns for real-time and offline-first editing. Use when building collaborative documents, shared scratchpads, or multi-user editing. Covers Y.Doc, Y.Map, Y.Array, Y.Text, state encoding, structured patches, server-side document manipulation, and conflict-free merge semantics.\nlicense: MIT\nallowed-tools: Read, Grep, Glob\nmetadata:\n  author: RevealUI Studio\n  version: \"0.1.0\"\n  website: https:\u002F\u002Frevealui.com\n---\n\n# Yjs CRDT Collaboration\n\n## Core Concepts\n\nYjs is a CRDT framework. Multiple peers can edit concurrently and merge without conflicts. Every operation is commutative and idempotent.\n\n```typescript\nimport * as Y from 'yjs';\n\nconst doc = new Y.Doc();\nconst root = doc.getMap('root');\n```\n\n## Type System\n\n| Type | Use Case | API |\n|------|----------|-----|\n| `Y.Map` | Key-value store | `set(key, val)`, `get(key)`, `delete(key)` |\n| `Y.Array` | Ordered list | `push([item])`, `insert(idx, [item])`, `delete(idx, len)` |\n| `Y.Text` | Rich\u002Fplain text | `insert(idx, str)`, `delete(idx, len)`, `toString()` |\n\nNested types: Y.Map values can be other shared types.\n\n```typescript\nconst root = doc.getMap('root');\n\n\u002F\u002F String values\nroot.set('title', 'My Document');\n\n\u002F\u002F Nested Y.Text\nconst findings = new Y.Text();\nfindings.insert(0, 'Initial finding...');\nroot.set('findings', findings);\n\n\u002F\u002F Nested Y.Array\nconst items = new Y.Array();\nitems.push(['Item 1', 'Item 2']);\nroot.set('items', items);\n```\n\n## State Encoding & Persistence\n\n```typescript\n\u002F\u002F Encode full state as a binary update\nconst state = Y.encodeStateAsUpdate(doc);       \u002F\u002F Uint8Array\nconst vector = Y.encodeStateVector(doc);          \u002F\u002F Uint8Array\n\n\u002F\u002F Persist to database (Postgres bytea column)\nawait db.update(documents)\n  .set({\n    state: Buffer.from(state),\n    stateVector: Buffer.from(vector),\n  })\n  .where(eq(documents.id, docId));\n\n\u002F\u002F Restore from database\nconst doc = new Y.Doc();\nY.applyUpdate(doc, new Uint8Array(storedState));\n```\n\n## Server-Side Document Manipulation\n\nFor CLI agents or batch processes that cannot use WebSocket:\n\n```typescript\nimport * as Y from 'yjs';\n\nfunction applyStructuredPatch(\n  existingState: Uint8Array | null,\n  patchType: string,\n  path: string,\n  content: string,\n): { state: Uint8Array; stateVector: Uint8Array } {\n  const doc = new Y.Doc();\n\n  if (existingState) {\n    Y.applyUpdate(doc, existingState);\n  }\n\n  const root = doc.getMap('root');\n\n  switch (patchType) {\n    case 'set_key':\n      root.set(path, content);\n      break;\n\n    case 'append_section': {\n      let section = root.get(path);\n      if (!(section instanceof Y.Text)) {\n        section = new Y.Text();\n        root.set(path, section);\n      }\n      section.insert(section.length, content);\n      break;\n    }\n\n    case 'append_item': {\n      let arr = root.get(path);\n      if (!(arr instanceof Y.Array)) {\n        arr = new Y.Array();\n        root.set(path, arr);\n      }\n      arr.push([content]);\n      break;\n    }\n\n    case 'replace_section': {\n      const text = new Y.Text();\n      text.insert(0, content);\n      root.set(path, text);\n      break;\n    }\n  }\n\n  const result = {\n    state: Y.encodeStateAsUpdate(doc),\n    stateVector: Y.encodeStateVector(doc),\n  };\n\n  doc.destroy();\n  return result;\n}\n```\n\n## Reading Document Content\n\n```typescript\nfunction readDocument(state: Uint8Array): Record\u003Cstring, unknown> {\n  const doc = new Y.Doc();\n  Y.applyUpdate(doc, state);\n  const root = doc.getMap('root');\n  const result: Record\u003Cstring, unknown> = {};\n\n  for (const [key, value] of root.entries()) {\n    if (value instanceof Y.Text) {\n      result[key] = value.toString();\n    } else if (value instanceof Y.Array) {\n      result[key] = value.toArray();\n    } else {\n      result[key] = value;\n    }\n  }\n\n  doc.destroy();\n  return result;\n}\n```\n\n## Merging Two Documents\n\n```typescript\n\u002F\u002F Two docs edited independently\nconst doc1 = new Y.Doc();\nconst doc2 = new Y.Doc();\n\n\u002F\u002F ... edits happen on each ...\n\n\u002F\u002F Merge: apply each doc's state to the other\nconst state1 = Y.encodeStateAsUpdate(doc1);\nconst state2 = Y.encodeStateAsUpdate(doc2);\n\nY.applyUpdate(doc1, state2); \u002F\u002F doc1 now has both edits\nY.applyUpdate(doc2, state1); \u002F\u002F doc2 now has both edits\n\u002F\u002F Both docs are identical after merge\n```\n\n## Database Schema\n\n```sql\nCREATE TABLE yjs_documents (\n  id TEXT PRIMARY KEY,\n  state BYTEA NOT NULL,\n  state_vector BYTEA,\n  connected_clients INTEGER NOT NULL DEFAULT 0,\n  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n  updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()\n);\n```\n\n## WebSocket Provider (Real-Time)\n\nFor browser agents that need live character-by-character collaboration:\n\n```typescript\nimport { WebsocketProvider } from 'y-websocket';\n\nconst doc = new Y.Doc();\nconst provider = new WebsocketProvider(\n  'wss:\u002F\u002Fcollab.example.com',\n  'document-id',\n  doc,\n);\n\nprovider.on('status', ({ status }) => {\n  console.log('Connection:', status); \u002F\u002F 'connecting' | 'connected' | 'disconnected'\n});\n```\n\n## Awareness (Presence)\n\n```typescript\nconst awareness = provider.awareness;\n\n\u002F\u002F Set local state (cursor position, user info)\nawareness.setLocalState({\n  user: { name: 'Agent A', color: '#ff0000' },\n  cursor: { index: 42, length: 0 },\n});\n\n\u002F\u002F Listen for remote state changes\nawareness.on('change', () => {\n  const states = awareness.getStates();\n  \u002F\u002F Map\u003CclientId, { user, cursor }>\n});\n```\n\n## Best Practices\n\n- Always call `doc.destroy()` after server-side operations to free memory\n- Use `Buffer.from(state)` when storing in Postgres bytea columns\n- Use `new Uint8Array(buffer)` when reading from Postgres bytea columns\n- Prefer `Y.Text` over plain strings for content that may be collaboratively edited\n- Use `Y.Array` for ordered lists (append-heavy patterns)\n- Use `Y.Map` as the root container for structured documents\n- Server-side patches and WebSocket edits merge cleanly via CRDT semantics\n","# Yjs CRDT Collaboration\n\n## Core Concepts\n\nYjs is a CRDT framework. Multiple peers can edit concurrently and merge without conflicts. Every operation is commutative and idempotent.\n\n```typescript\nimport * as Y from 'yjs';\n\nconst doc = new Y.Doc();\nconst root = doc.getMap('root');\n```\n\n## Type System\n\n| Type | Use Case | API |\n|------|----------|-----|\n| `Y.Map` | Key-value store | `set(key, val)`, `get(key)`, `delete(key)` |\n| `Y.Array` | Ordered list | `push([item])`, `insert(idx, [item])`, `delete(idx, len)` |\n| `Y.Text` | Rich\u002Fplain text | `insert(idx, str)`, `delete(idx, len)`, `toString()` |\n\nNested types: Y.Map values can be other shared types.\n\n```typescript\nconst root = doc.getMap('root');\n\n\u002F\u002F String values\nroot.set('title', 'My Document');\n\n\u002F\u002F Nested Y.Text\nconst findings = new Y.Text();\nfindings.insert(0, 'Initial finding...');\nroot.set('findings', findings);\n\n\u002F\u002F Nested Y.Array\nconst items = new Y.Array();\nitems.push(['Item 1', 'Item 2']);\nroot.set('items', items);\n```\n\n## State Encoding & Persistence\n\n```typescript\n\u002F\u002F Encode full state as a binary update\nconst state = Y.encodeStateAsUpdate(doc);       \u002F\u002F Uint8Array\nconst vector = Y.encodeStateVector(doc);          \u002F\u002F Uint8Array\n\n\u002F\u002F Persist to database (Postgres bytea column)\nawait db.update(documents)\n  .set({\n    state: Buffer.from(state),\n    stateVector: Buffer.from(vector),\n  })\n  .where(eq(documents.id, docId));\n\n\u002F\u002F Restore from database\nconst doc = new Y.Doc();\nY.applyUpdate(doc, new Uint8Array(storedState));\n```\n\n## Server-Side Document Manipulation\n\nFor CLI agents or batch processes that cannot use WebSocket:\n\n```typescript\nimport * as Y from 'yjs';\n\nfunction applyStructuredPatch(\n  existingState: Uint8Array | null,\n  patchType: string,\n  path: string,\n  content: string,\n): { state: Uint8Array; stateVector: Uint8Array } {\n  const doc = new Y.Doc();\n\n  if (existingState) {\n    Y.applyUpdate(doc, existingState);\n  }\n\n  const root = doc.getMap('root');\n\n  switch (patchType) {\n    case 'set_key':\n      root.set(path, content);\n      break;\n\n    case 'append_section': {\n      let section = root.get(path);\n      if (!(section instanceof Y.Text)) {\n        section = new Y.Text();\n        root.set(path, section);\n      }\n      section.insert(section.length, content);\n      break;\n    }\n\n    case 'append_item': {\n      let arr = root.get(path);\n      if (!(arr instanceof Y.Array)) {\n        arr = new Y.Array();\n        root.set(path, arr);\n      }\n      arr.push([content]);\n      break;\n    }\n\n    case 'replace_section': {\n      const text = new Y.Text();\n      text.insert(0, content);\n      root.set(path, text);\n      break;\n    }\n  }\n\n  const result = {\n    state: Y.encodeStateAsUpdate(doc),\n    stateVector: Y.encodeStateVector(doc),\n  };\n\n  doc.destroy();\n  return result;\n}\n```\n\n## Reading Document Content\n\n```typescript\nfunction readDocument(state: Uint8Array): Record\u003Cstring, unknown> {\n  const doc = new Y.Doc();\n  Y.applyUpdate(doc, state);\n  const root = doc.getMap('root');\n  const result: Record\u003Cstring, unknown> = {};\n\n  for (const [key, value] of root.entries()) {\n    if (value instanceof Y.Text) {\n      result[key] = value.toString();\n    } else if (value instanceof Y.Array) {\n      result[key] = value.toArray();\n    } else {\n      result[key] = value;\n    }\n  }\n\n  doc.destroy();\n  return result;\n}\n```\n\n## Merging Two Documents\n\n```typescript\n\u002F\u002F Two docs edited independently\nconst doc1 = new Y.Doc();\nconst doc2 = new Y.Doc();\n\n\u002F\u002F ... edits happen on each ...\n\n\u002F\u002F Merge: apply each doc's state to the other\nconst state1 = Y.encodeStateAsUpdate(doc1);\nconst state2 = Y.encodeStateAsUpdate(doc2);\n\nY.applyUpdate(doc1, state2); \u002F\u002F doc1 now has both edits\nY.applyUpdate(doc2, state1); \u002F\u002F doc2 now has both edits\n\u002F\u002F Both docs are identical after merge\n```\n\n## Database Schema\n\n```sql\nCREATE TABLE yjs_documents (\n  id TEXT PRIMARY KEY,\n  state BYTEA NOT NULL,\n  state_vector BYTEA,\n  connected_clients INTEGER NOT NULL DEFAULT 0,\n  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n  updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()\n);\n```\n\n## WebSocket Provider (Real-Time)\n\nFor browser agents that need live character-by-character collaboration:\n\n```typescript\nimport { WebsocketProvider } from 'y-websocket';\n\nconst doc = new Y.Doc();\nconst provider = new WebsocketProvider(\n  'wss:\u002F\u002Fcollab.example.com',\n  'document-id',\n  doc,\n);\n\nprovider.on('status', ({ status }) => {\n  console.log('Connection:', status); \u002F\u002F 'connecting' | 'connected' | 'disconnected'\n});\n```\n\n## Awareness (Presence)\n\n```typescript\nconst awareness = provider.awareness;\n\n\u002F\u002F Set local state (cursor position, user info)\nawareness.setLocalState({\n  user: { name: 'Agent A', color: '#ff0000' },\n  cursor: { index: 42, length: 0 },\n});\n\n\u002F\u002F Listen for remote state changes\nawareness.on('change', () => {\n  const states = awareness.getStates();\n  \u002F\u002F Map\u003CclientId, { user, cursor }>\n});\n```\n\n## Best Practices\n\n- Always call `doc.destroy()` after server-side operations to free memory\n- Use `Buffer.from(state)` when storing in Postgres bytea columns\n- Use `new Uint8Array(buffer)` when reading from Postgres bytea columns\n- Prefer `Y.Text` over plain strings for content that may be collaboratively edited\n- Use `Y.Array` for ordered lists (append-heavy patterns)\n- Use `Y.Map` as the root container for structured documents\n- Server-side patches and WebSocket edits merge cleanly via CRDT semantics\n",{"name":5,"license":14,"metadata":48,"description":7,"allowed-tools":52},{"author":49,"version":50,"website":51},"RevealUI Studio","0.1.0","https:\u002F\u002Frevealui.com","Read, Grep, Glob","test","2b46ce0cfb27f77a7b78cfb49b0b004e2072b7ba","skills\u002Fyjs-collaboration",0,"https:\u002F\u002Fgithub.com\u002Frevealui-studio\u002Frevskills","https:\u002F\u002Fgithub.com\u002Frevealui-studio","2026-11-11 23:29:48",{"source":8,"skillName":5,"commands":61,"prompt":71,"zipAvailable":72},[62,65,68],{"tool":63,"command":64},"npx","npx skills add revealui-studio\u002Frevskills --skill yjs-collaboration",{"tool":66,"command":67},"bunx","bunx skills add revealui-studio\u002Frevskills --skill yjs-collaboration",{"tool":69,"command":70},"pnpm","pnpm dlx skills add revealui-studio\u002Frevskills --skill yjs-collaboration","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Frevealui-studio\u002Frevskills\u002Fblob\u002Ftest\u002Fskills\u002Fyjs-collaboration\u002FSKILL.md",true,[],[75,99,111,125,162,186],{"skillNo":76,"name":77,"nameZh":6,"description":78,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":79,"categories":80,"keywords":84,"publishedAt":43},"01M6NNN0QCBBPEW3V3C4SBETRZ","good-skill","A minimal valid skill fixture used to prove the skills-lint and plugin-lint validators accept well formed input. Covers frontmatter shape only.","https:\u002F\u002Fgithub.com\u002Frevealui-studio\u002Frevskills\u002Fblob\u002Ftest\u002Ftest\u002Ffixtures\u002Fskills\u002Fgood-skill\u002FSKILL.md",[81],{"categoryNo":82,"categoryName":83,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000023","Skill与智能体开发",[85,86,87,88,89,90,91,92,93,94,95,96,97,98],"good","good skill","well formed","frontmatter","skill fixture","plugin","input","fixture","minimal","shape","only","lint","valid skill","valid",{"skillNo":100,"name":101,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":102,"categories":103,"keywords":105,"publishedAt":43},"01M6NNMY4GWFD65V1Q2W5YC465","bad-skill-missing-field","https:\u002F\u002Fgithub.com\u002Frevealui-studio\u002Frevskills\u002Fblob\u002Ftest\u002Ftest\u002Ffixtures\u002Fskills\u002Fbad-skill-missing-field\u002FSKILL.md",[104],{"categoryNo":82,"categoryName":83,"taxonomyType":20,"taxonomyTypeDesc":21},[106,107,108,109,110],"bad skill","bad","missing","missing field","bad skill missing field",{"skillNo":112,"name":113,"nameZh":6,"description":114,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":115,"categories":116,"keywords":118,"publishedAt":43},"01M6NNMF7WN6C308H8CGJVRBCB","bad-skill-awk","Fixture skill whose fenced shell block violates lint-skill.awk. skills-lint must reject it.","https:\u002F\u002Fgithub.com\u002Frevealui-studio\u002Frevskills\u002Fblob\u002Ftest\u002Ftest\u002Ffixtures\u002Fskills\u002Fbad-skill-awk\u002FSKILL.md",[117],{"categoryNo":82,"categoryName":83,"taxonomyType":20,"taxonomyTypeDesc":21},[106,107,119,120,96,121,122,92,123,124],"awk","bad skill awk","shell","fixture skill","it","block",{"skillNo":126,"name":127,"nameZh":6,"description":128,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":129,"categories":130,"keywords":142,"publishedAt":43},"01M6NNM6VE7WE8ZAWQFS4AZE1P","vitest-testing","Vitest testing patterns for production TypeScript projects. Use when writing tests, fixing test failures, configuring coverage, mocking modules, debugging flaky tests, or setting up Vitest in a monorepo. Covers Vitest 3+, vi.mock, vi.fn, React Testing Library, PGlite in-memory PostgreSQL, pool forks, maxWorkers, and hookTimeout.","https:\u002F\u002Fgithub.com\u002Frevealui-studio\u002Frevskills\u002Fblob\u002Ftest\u002Fskills\u002Fvitest-testing\u002FSKILL.md",[131,134,137],{"categoryNo":132,"categoryName":133,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000008","测试与质量",{"categoryNo":135,"categoryName":136,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000018","写作与文案",{"categoryNo":138,"categoryName":139,"taxonomyType":140,"taxonomyTypeDesc":141},"01JBSEEDCAT000000000000036","内容创作者","PROFESSION","适用职业",[143,144,145,27,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161],"vitest","vitest testing","testing","react testing library","mocking","mock","tests","react testing","modules","up","use","coverage","projects","testing patterns","testing library","debugging","memory","writing","monorepo",{"skillNo":163,"name":164,"nameZh":6,"description":165,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":166,"categories":167,"keywords":168,"publishedAt":43},"01M6NNKSJ6TJBVPDN3YJHK5B70","tailwind-v4","Tailwind CSS v4 patterns, CSS-first configuration, and v3 migration guide. Use when writing styles, configuring @theme variables, creating components with CVA, migrating from tailwind.config.js, or using container queries, dark mode, and new v4 utility syntax. Covers @import tailwindcss, custom properties, oklch colors, and clsx.","https:\u002F\u002Fgithub.com\u002Frevealui-studio\u002Frevskills\u002Fblob\u002Ftest\u002Fskills\u002Ftailwind-v4\u002FSKILL.md",[],[169,170,171,172,173,160,153,28,174,175,176,177,178,179,180,181,182,183,184,185],"tailwind v4","Tailwind","components","tailwindcss","css","dark","custom","mode","Variables","with","theme","utility","import","dark mode","v3","queries","container",{"skillNo":187,"name":188,"nameZh":6,"description":189,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":190,"categories":191,"keywords":192,"publishedAt":43},"01M6NNKJ0KEE13SARX50HNHNGG","security-hardening","Web application security hardening for OWASP Top 10 vulnerabilities. Use when implementing authentication, HTTP security headers, CORS, rate limiting, input validation, or reviewing code for XSS, SQL injection, CSRF, or SSRF. Covers CSP, HSTS, session cookies, bcrypt, Zod validation, and secrets management.","https:\u002F\u002Fgithub.com\u002Frevealui-studio\u002Frevskills\u002Fblob\u002Ftest\u002Fskills\u002Fsecurity-hardening\u002FSKILL.md",[],[193,194,195,196,36,197,198,199,28,200,201,202,203,204,205,206,207,208,209,210],"security","security hardening","hardening","application security","zod validation","implementing","top","headers","Input Validation","zod","secrets","secrets management","csrf","xss","authentication","code","owasp top 10","sql"]