{"id":51167062,"url":"https://github.com/navapbc/skills-registry","last_synced_at":"2026-06-26T20:30:21.639Z","repository":{"id":362123246,"uuid":"1246066194","full_name":"navapbc/skills-registry","owner":"navapbc","description":"Browse, install, and share reusable AI skills across Nava","archived":false,"fork":false,"pushed_at":"2026-06-24T16:07:41.000Z","size":2670,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-24T18:06:11.566Z","etag":null,"topics":["ai-skills","astro","aws","claude","internal-tools"],"latest_commit_sha":null,"homepage":"https://hub.navapbc.com","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/navapbc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-21T20:53:56.000Z","updated_at":"2026-06-24T16:08:35.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/navapbc/skills-registry","commit_stats":null,"previous_names":["navapbc/skills-registry"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/navapbc/skills-registry","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/navapbc%2Fskills-registry","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/navapbc%2Fskills-registry/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/navapbc%2Fskills-registry/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/navapbc%2Fskills-registry/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/navapbc","download_url":"https://codeload.github.com/navapbc/skills-registry/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/navapbc%2Fskills-registry/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34832916,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-26T02:00:06.560Z","response_time":106,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-skills","astro","aws","claude","internal-tools"],"created_at":"2026-06-26T20:30:20.390Z","updated_at":"2026-06-26T20:30:21.633Z","avatar_url":"https://github.com/navapbc.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Nava Skills Hub\n\nA skills marketplace for the navapbc org — scans `SKILL.md`, `AGENT.md`, and `.claude/skills/*.md` files across all repos and surfaces them in a searchable, authenticated UI.\n\n**Stack:** Astro (static frontend) · AWS S3 + CloudFront · API Gateway · Lambda (Auth + API) · DynamoDB · GitHub Actions · Terraform · pnpm\n\n**Live environments:**\n- Staging: https://staging.hub.navapbc.com (deploys from `main`)\n- Prod: https://hub.navapbc.com (deploys from `release`)\n\n---\n\n## Architecture\n\n```\nGitHub Org (navapbc)\n  └── any repo with SKILL.md / AGENT.md / .claude/skills/*.md\n        │\n        ▼  (sync-registry workflow, every 4h)\n     DynamoDB (skills-registry-skills-{env})\n        │\n        ▼\nBrowser → CloudFront (edge JWT check)\n               │\n               ├─ /auth/*   → Auth Lambda (Google OAuth, issues __session cookie)\n               ├─ /api/*    → API Gateway → API Lambda → DynamoDB\n               └─ /*        → S3 (static Astro build)\n```\n\n- **CloudFront Function** runs on every viewer request and validates the `__session` JWT. Unauthenticated requests are redirected to `/login`.\n- **Auth Lambda** handles `/auth/login`, `/auth/callback`, and `/auth/logout`. Restricts to `@navapbc.com` accounts. Issues an 8-hour JWT cookie. Proxied through CloudFront so the cookie lands on the hub domain.\n- **API Lambda** (Hono router) handles all `/api/*` routes — CRUD for skills, plugins, users, and audit log. Validates the same JWT on every request.\n- **S3** hosts the compiled Astro build output.\n- No containers, no servers.\n\n---\n\n## Database (DynamoDB)\n\nFour tables per environment (`skills-registry-{table}-{env}`):\n\n| Table | What's stored |\n|---|---|\n| `skills` | All skill and agent records — from GitHub repos, the `enterprise/` folder in this repo, Anthropic built-ins, and user-submitted. Fields: `slug`, `name`, `description`, `type` (skill/agent), `plugin`, `repo`, `path`, `author`, `compatibility`, `source`, `status` (pending/approved/rejected), `visibility`, `content`, `tags`, `category`, `created_by`, `created_at`, `updated_at`. |\n| `plugins` | Plugin groupings (e.g. a tool namespace containing multiple skills). Fields: `slug`, `name`, `description`, `repo`, `author`, `skills_count`, `status`, `visibility`. |\n| `users` | One record per authenticated user, created on first API call. Fields: `user_id` (email), `role` (user/maintain/admin), `name`, `avatar_url`, `favorites` (skill slugs), `installed`, `created_at`, `last_seen_at`. |\n| `audit-log` | Append-only log of create/update/delete/approve/reject/role-change events. Fields: `user_id`, `event_key` (ISO timestamp + UUID), `action`, `resource_type`, `resource_id`, `metadata`. |\n\n**Not stored in DynamoDB:** JWT session state (stateless signed cookies), Google OAuth tokens (discarded after callback), raw GitHub file content beyond what's in the `content` field.\n\n**Admin promotion:** The first admin must be set directly via DynamoDB CLI. Subsequent role changes go through the admin UI (`PUT /api/users/:id/role`).\n\n```bash\naws dynamodb update-item \\\n  --table-name skills-registry-users-staging \\\n  --key '{\"user_id\":{\"S\":\"your@navapbc.com\"}}' \\\n  --update-expression \"SET #r = :r\" \\\n  --expression-attribute-names '{\"#r\":\"role\"}' \\\n  --expression-attribute-values '{\":r\":{\"S\":\"admin\"}}' \\\n  --region us-east-1\n```\n\n---\n\n## Prerequisites\n\n- AWS account with permissions to create S3, CloudFront, Lambda, API Gateway, DynamoDB, SSM, IAM\n- Terraform \u003e= 1.7\n- Node.js \u003e= 22\n- pnpm \u003e= 10\n- A Google Cloud project with OAuth 2.0 credentials configured\n\nSee [docs/DEPLOY.md](docs/DEPLOY.md) for complete first-time setup instructions. See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for a full technical deep-dive. See [docs/api.md](docs/api.md) for the API reference ([OpenAPI spec](docs/openapi.yaml)) and [SECURITY.md](SECURITY.md) for the security model.\n\n---\n\n## Deploying\n\nDeploys are triggered automatically by CI:\n\n| Branch | Environment | Domain |\n|---|---|---|\n| `main` | staging | `staging.hub.navapbc.com` |\n| `release` | prod | `hub.navapbc.com` |\n\nEach deploy: runs tests → builds Astro site → syncs to S3 → invalidates CloudFront → deploys auth Lambda → deploys API Lambda.\n\nTo deploy to prod:\n```bash\ngit checkout release\ngit merge main\ngit push origin release\n```\n\nThe `production` GitHub environment requires reviewer approval before the deploy runs.\n\n---\n\n## GitHub Actions secrets\n\nTwo GitHub environments (`staging`, `production`) each need:\n\n| Secret | Source |\n|---|---|\n| `AWS_DEPLOY_ROLE_ARN` | `terraform output github_deploy_role_arn` |\n| `AWS_S3_BUCKET_NAME` | `terraform output s3_bucket_name` |\n| `AWS_CLOUDFRONT_DISTRIBUTION_ID` | `terraform output cloudfront_distribution_id` |\n| `AWS_AUTH_LAMBDA_FUNCTION_NAME` | `terraform output lambda_auth_function_name` |\n| `AWS_API_LAMBDA_FUNCTION_NAME` | `terraform output api_lambda_function_name` |\n| `AUTH_LAMBDA_URL` | `terraform output login_url` (used as `PUBLIC_LOGIN_URL` in Astro build) |\n\nRepository-level (not environment-scoped):\n\n| Secret | Purpose |\n|---|---|\n| `REGISTRY_SCAN_TOKEN` | Fine-grained PAT with `Contents: Read` + `Metadata: Read` on navapbc repos |\n| `ANTHROPIC_API_KEY` | Used by the weekly Anthropic built-in skills sync |\n\n---\n\n## IAM Role for GitHub Actions (OIDC)\n\nCreate an IAM role trusted by GitHub Actions OIDC with a policy allowing:\n- `s3:PutObject`, `s3:DeleteObject`, `s3:GetObject`, `s3:ListBucket` on the site bucket\n- `cloudfront:CreateInvalidation`, `cloudfront:GetInvalidation`, `cloudfront:ListInvalidations`\n- `lambda:UpdateFunctionCode`, `lambda:GetFunction`, `lambda:GetFunctionConfiguration` on both auth and API Lambdas\n- `dynamodb:PutItem`, `dynamodb:GetItem`, `dynamodb:UpdateItem` on the skills and plugins tables (for sync scripts)\n\nSee [AWS docs on GitHub OIDC](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html). Terraform provisions this automatically via `terraform/iam.tf`.\n\n---\n\n## Scheduled workflows\n\n| Schedule | Workflow | What it does |\n|---|---|---|\n| Every 4 hours | `sync.yml` | Scans GitHub org for SKILL.md/AGENT.md files + `enterprise/` folder, writes to DynamoDB |\n| Mondays 9am UTC | `sync-anthropic.yml` | Fetches Anthropic built-in skills via API, writes to DynamoDB |\n\nTrigger either manually from the Actions tab (`workflow_dispatch`). The sync workflow defaults to staging; select `production` for prod.\n\n---\n\n## Adding skills to a repo\n\nAdd a `SKILL.md` at the root of any navapbc repo (or in `.claude/skills/`, `.agents/skills/`, etc.). Most frontmatter fields are optional — the pipeline derives what it can from the file path, repo metadata, and the first line of the body. At minimum, just `name` and `description` get a useful record:\n\n```yaml\n---\nname: plain-language\ndescription: When the user wants to rewrite government or technical content in plain language for a general audience.\nauthor: your-github-handle\nversion: 1.0.0\ncompatibility: [claude-chat, claude-cowork, claude-code]\nsensitive_data: false\ncategory: writing\ntags: [plain-language, writing, accessibility]\n---\n\nYour skill content here...\n```\n\nFor agents, add `agents/my-agent/AGENT.md` with the additional agent fields:\n\n```yaml\n---\nname: snap-eligibility-agent\ndescription: When the user wants to run a full SNAP eligibility review.\nauthor: your-github-handle\nversion: 1.0.0\ncompatibility: [claude-code]\nsensitive_data: true\ntype: agent\ntools_used: [skill-one, skill-two]\nhuman_in_loop: Describe where human review happens before outputs are used\n---\n```\n\nSee [`registry/schema.md`](registry/schema.md) for the complete frontmatter field reference — required vs. optional, defaults, agent-only fields, and submission metadata fields.\n\nEnterprise-only skills (not sourced from a public GitHub repo) go in `enterprise/\u003cslug\u003e/SKILL.md` in this repository. They're synced directly via the Git Trees API, bypassing GitHub's search indexing delay.\n\nThe sync runs every 4 hours. Trigger it manually from the Actions tab for immediate pickup.\n\n---\n\n## Local Development\n\n```bash\npnpm install\npnpm dev          # Astro dev server at http://localhost:4321\npnpm sync:v2      # Sync GitHub org skills into DynamoDB (requires AWS + GITHUB_TOKEN)\npnpm test         # Run vitest test suite\n```\n\nThe dev server doesn't enforce auth — CloudFront auth only runs in AWS. API calls from the local dev server will fail unless you have a valid `__session` cookie or run against a deployed environment.\n\n---\n\n## Styles\n\nThe site uses Tailwind CSS v4 (via `@tailwindcss/vite`). Global styles are in `public/styles/main.css`. See `src/layouts/Base.astro` for class naming conventions.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnavapbc%2Fskills-registry","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnavapbc%2Fskills-registry","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnavapbc%2Fskills-registry/lists"}