{"id":51853860,"url":"https://github.com/somoore/powerpipe-turbopuffer-security-benchmark","last_synced_at":"2026-07-23T22:30:34.008Z","repository":{"id":369993539,"uuid":"1292698781","full_name":"somoore/powerpipe-turbopuffer-security-benchmark","owner":"somoore","description":"Powerpipe mod: 16 security controls (tenant isolation, data residency, CMEK, schema hygiene, ops) and branded dashboards for turbopuffer namespaces. Runs over the somoore/turbopuffer Steampipe plugin.","archived":false,"fork":false,"pushed_at":"2026-07-07T20:15:50.000Z","size":314,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-07T21:09:14.259Z","etag":null,"topics":["compliance","powerpipe","powerpipe-mod","security","sql","steampipe","turbopuffer","vector-search"],"latest_commit_sha":null,"homepage":"https://github.com/somoore/steampipe-plugin-turbopuffer","language":"Puppet","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/somoore.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":null,"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-07-07T19:05:58.000Z","updated_at":"2026-07-07T20:15:53.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/somoore/powerpipe-turbopuffer-security-benchmark","commit_stats":null,"previous_names":["somoore/powerpipe-turbopuffer-security-benchmark"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/somoore/powerpipe-turbopuffer-security-benchmark","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/somoore%2Fpowerpipe-turbopuffer-security-benchmark","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/somoore%2Fpowerpipe-turbopuffer-security-benchmark/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/somoore%2Fpowerpipe-turbopuffer-security-benchmark/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/somoore%2Fpowerpipe-turbopuffer-security-benchmark/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/somoore","download_url":"https://codeload.github.com/somoore/powerpipe-turbopuffer-security-benchmark/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/somoore%2Fpowerpipe-turbopuffer-security-benchmark/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35819442,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-07-20T02:08:10.276Z","status":"online","status_checked_at":"2026-07-23T02:00:06.683Z","response_time":57,"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":["compliance","powerpipe","powerpipe-mod","security","sql","steampipe","turbopuffer","vector-search"],"created_at":"2026-07-23T22:30:33.375Z","updated_at":"2026-07-23T22:30:34.000Z","avatar_url":"https://github.com/somoore.png","language":"Puppet","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cpicture\u003e\n  \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"docs/images/turbopuffer-lockup-dark.svg\"\u003e\n  \u003cimg alt=\"turbopuffer\" src=\"docs/images/turbopuffer-lockup-light.svg\" width=\"360\"\u003e\n\u003c/picture\u003e\n\n# turbopuffer Security Benchmark Mod for Powerpipe\n\nRun individual tenant-isolation, data-residency, encryption, schema-hygiene and operations controls — or the full security benchmark — across your [turbopuffer](https://turbopuffer.com) namespaces using [Powerpipe](https://powerpipe.io) and [Steampipe](https://steampipe.io).\n\n\u003e Unofficial community project. Not affiliated with or endorsed by turbopuffer inc. All read-only.\n\nRun checks in a dashboard:\n\n![turbopuffer Security Benchmark dashboard](docs/images/benchmark.png)\n\n## Why\n\nturbopuffer's own permissions documentation is explicit: row/document-level access control is the **application's** responsibility, implemented via attribute filters. There is no built-in RBAC below the API-key level. That's a reasonable architectural choice — and it means every turbopuffer customer is one missing schema attribute or one non-filterable field away from cross-tenant retrieval. Nothing audits that today. This does.\n\n## What gets checked\n\n| # | Control | Severity | Signal |\n|---|---------|----------|--------|\n| 1 | `tenant_isolation_acl_attributes_present` | critical | Tenant namespaces define the ACL attributes your filters depend on |\n| 2 | `tenant_isolation_acl_attributes_filterable` | critical | …and those attributes are actually `filterable` (BM25 fields aren't, by default) |\n| 3 | `tenant_isolation_namespace_naming` | medium | Namespaces match the naming convention other controls key off |\n| 4 | `tenant_isolation_canary_document_present` | high | Honeytoken doc seeded per namespace (alert on its retrieval in your app logs) |\n| 5 | `residency_approved_regions_only` | high | Namespaces only in approved regions |\n| 6 | `residency_eu_namespaces_in_eu_regions` | critical | EU-tagged namespaces hosted in EU regions |\n| 7 | `encryption_cmek_on_sensitive_namespaces` | high | Prod/PII namespaces use customer-managed keys |\n| 8 | `encryption_cmek_keys_approved` | medium | CMEK keys come from the approved key inventory |\n| 9 | `hygiene_sensitive_attribute_names` | high | No `ssn`/`card_number`/`api_key`-style attributes next to your vectors |\n| 10 | `hygiene_sensitive_attributes_not_search_indexed` | high | Sensitive attrs aren't FTS/regex/glob/fuzzy-indexed (exposure amplification) |\n| 11 | `hygiene_schema_drift_across_environments` | medium | `prod-x` and `staging-x` schemas match |\n| 12 | `hygiene_empty_namespaces` | low | No abandoned empty namespaces |\n| 13 | `ops_stale_namespaces` | medium | Every namespace has an owner writing to it (`updated_at` recency) |\n| 14 | `ops_index_lag` | medium | No unindexed WAL bytes — recent writes are searchable, not silently missed |\n| 15 | `ops_oversized_namespaces` | medium | Single-namespace blast radius under threshold |\n| 16 | `ops_namespace_sprawl` | low | Total namespace count within budget |\n\nEverything is tunable in `variables.pp`.\n\n## Getting Started\n\n### Installation\n\nInstall [Powerpipe](https://powerpipe.io/downloads), or use Brew:\n\n```bash\nbrew install turbot/tap/powerpipe\n```\n\nThis mod requires [Steampipe](https://steampipe.io) with the [turbopuffer plugin](https://github.com/somoore/steampipe-plugin-turbopuffer) as the data source. Install Steampipe (https://steampipe.io/downloads), or use Brew:\n\n```bash\nbrew install turbot/tap/steampipe\n```\n\nThe plugin has [shipped its first release](https://github.com/somoore/steampipe-plugin-turbopuffer/releases) and is submitted to the Steampipe Hub, but isn't listed there yet — so `steampipe plugin install somoore/turbopuffer` won't resolve until that goes live. Until then, install from the GitHub release:\n\n```bash\n# darwin/arm64 shown; swap for your OS/arch from the releases page\ncurl -L -o turbopuffer.plugin.gz \\\n  https://github.com/somoore/steampipe-plugin-turbopuffer/releases/latest/download/steampipe-plugin-turbopuffer_darwin_arm64.gz\ngunzip turbopuffer.plugin.gz\nmkdir -p ~/.steampipe/plugins/local/turbopuffer\nmv turbopuffer.plugin ~/.steampipe/plugins/local/turbopuffer/turbopuffer.plugin\nchmod +x ~/.steampipe/plugins/local/turbopuffer/turbopuffer.plugin\n```\n\nOnce Hub listing lands, switch back to `steampipe plugin install somoore/turbopuffer` and use `plugin = \"somoore/turbopuffer\"` in your connection config below.\n\nConfigure your connection with a turbopuffer API key and the regions to scan (see the [plugin's sample config](https://github.com/somoore/steampipe-plugin-turbopuffer/blob/main/config/turbopuffer.spc) and [docs](https://github.com/somoore/steampipe-plugin-turbopuffer)):\n\n```bash\ncurl -o ~/.steampipe/config/turbopuffer.spc \\\n  https://raw.githubusercontent.com/somoore/steampipe-plugin-turbopuffer/main/config/turbopuffer.spc\n$EDITOR ~/.steampipe/config/turbopuffer.spc   # api_key + regions\n# if you installed manually above, also change: plugin = \"local/turbopuffer\"\n```\n\nFinally, install the mod (only needed if you're pulling this mod into another workspace as a dependency — skip this if you've cloned this repo directly, just `cd` into it):\n\n```bash\nmkdir dashboards\ncd dashboards\npowerpipe mod init\npowerpipe mod install github.com/somoore/powerpipe-turbopuffer-security-benchmark\n```\n\n\u003e Until the plugin is listed on the Hub, `mod install` fails with a plugin-version error (manually-installed plugins report their version as `local`, which can't satisfy any `min_version` check). `powerpipe benchmark run` and `powerpipe server` still work fine against a direct clone — that error is only a blocker for the dependency-install path above.\n\n### Browsing Dashboards\n\nStart Steampipe as the data source:\n\n```bash\nsteampipe service start\n```\n\nStart the dashboard server:\n\n```bash\npowerpipe server\n```\n\nBrowse and view your dashboards at **http://localhost:9033**.\n\nTwo branded dashboards ship with the mod:\n\n- **turbopuffer: Security Posture** — box-drawn hero and Step 1/2/3 panels echoing the onboarding page, posture cards that flip coral on alert, and a Largest Namespaces table that drills into…\n- **turbopuffer: Namespace Detail** — a namespace selector, size/freshness/encryption cards, a **Tenant Isolation: ready / NOT enforceable** verdict card (required ACL attributes present *and* filterable), and the full attribute schema with search-amplification flags.\n\n### Running Checks in Your Terminal\n\nInstead of running benchmarks in a dashboard, you can run them in your terminal with the `powerpipe benchmark` command:\n\nList available benchmarks:\n\n```bash\npowerpipe benchmark list\n```\n\nRun the benchmark:\n\n```bash\npowerpipe benchmark run turbopuffer_security \\\n  --var 'required_acl_attributes=[\"tenant_id\"]' \\\n  --var 'approved_regions=[\"gcp-us-central1\"]'\n```\n\nDifferent output formats are also available — for more information see [Output Formats](https://powerpipe.io/docs/reference/cli/benchmark#output-formats).\n\n## The data source\n\nThis mod queries the tables exposed by the [turbopuffer Steampipe plugin](https://github.com/somoore/steampipe-plugin-turbopuffer):\n\n| Table | One row per | Notable columns |\n|-------|-------------|-----------------|\n| `turbopuffer_namespace` | namespace × region | `approx_row_count`, `approx_logical_bytes`, `created_at`, `updated_at`, `encryption_mode`, `encryption_key_name`, `index_status`, `schema` |\n| `turbopuffer_namespace_attribute` | schema attribute | `type`, `filterable`, `full_text_search`, `regex`, `glob`, `fuzzy`, `vector_index`, `sparse_vector_index` |\n| `turbopuffer_document` | document (requires `namespace` qual) | `id`, `attributes` — vectors always excluded; built for canary lookups, not export |\n| `turbopuffer_namespace_recall` | recall evaluation (requires `namespace` qual) | `avg_recall`, `avg_ann_count`, `avg_exhaustive_count` — index-integrity signal |\n| `turbopuffer_region` | configured region | `region`, `endpoint` — join anchor for residency queries |\n\nBecause it's all SQL in Steampipe, these join against the other 150+ plugins: put turbopuffer residency next to `aws_s3_bucket` residency in one report, or join namespaces against a `tenants.csv` to catch orphaned tenants.\n\n## Grounding \u0026 honesty notes\n\n- Endpoint paths and response fields were **verified against the official `turbopuffer-go/v2` client and the [turbopuffer OpenAPI spec](https://github.com/turbopuffer/turbopuffer-openapi)**, then confirmed against a live account. The metadata response is what makes CMEK, staleness, and index-lag controls real rather than aspirational.\n- **Compiled, tested, and run against a live account** (0 errors against seeded live data, load-tested to 1,200+ namespaces).\n- **The control-plane gap**: turbopuffer's public API is data-plane only. API keys, permissions, org membership and billing are dashboard-only — that's why there's no `turbopuffer_api_key` table. Track what you can't check; that list is the roadmap.\n\n## Open Source \u0026 Contributing\n\nThis repository is published under the [Apache 2.0 license](https://www.apache.org/licenses/LICENSE-2.0). [Steampipe](https://steampipe.io) and [Powerpipe](https://powerpipe.io) are products produced by [Turbot HQ, Inc](https://turbot.com); this mod is an independent community project and is not affiliated with Turbot or turbopuffer inc.\n\nturbopuffer logos are used under turbopuffer's [brand guidelines](https://turbopuffer.com/press).\n\n## Get Involved\n\n**[Join #powerpipe on Slack →](https://turbot.com/community/join)**\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsomoore%2Fpowerpipe-turbopuffer-security-benchmark","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsomoore%2Fpowerpipe-turbopuffer-security-benchmark","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsomoore%2Fpowerpipe-turbopuffer-security-benchmark/lists"}