公开记录
软件健康报告模式 0.27.0 · 指标 1.13.0 · 2026-07-24 03:58 UTC

asyncdotengineering / porulle

Headless commerce framework for TypeScript. REST-only, security-hardened, self-host-first. Active development, alpha — straight out of the oven.

TypeScript · MDXMIT★ 0 星标⑂ 0 复刻始于 2026年5月在 GitHub 上查看 ↗

asyncdotengineering/porulle 的健康指数为 100 分中的 54 分,处于「中等」区间。 其得分最高的类别是Vitality(74/100),最低的是Community & Adoption(35/100)。 最近一次更新在 5 天前。 近期的大部分工作由 1 位贡献者完成。

54
总分 / 100
中等

软件健康指数

指标归入加权类别,统一采用 1–100 量表。总体分先取类别加权平均;当公开证据触发高风险司法辖区政策时,评级会按政策调整,并设置 49(有风险)的上限。AI 就绪度不计入总体分。

54
优秀85-100堪称典范;基本满足所有检验标准
良好70-84健康;仅有轻微不足
中等50-69可接受,但存在明显不足;建议进行审查
存在风险30-49存在重大薄弱环节;采用时应保持审慎
危急1-29问题严重(项目被弃置、仅有单一维护者、缺乏基本工程规范)
活力社区与采用可持续性与治理工程质量安全AI 就绪度

评分画像

每条轴代表一个类别。形状比平均值更重要——健康的对象会填满整个图形,而“一峰一谷”式画像意味着某一维度的优势正掩盖另一维度的风险。

所有权

0 关注者9 个公开仓库始于 2023年4月

该仓库由组织支持——共同承担、可问责的托管责任,可延续于任何单一维护者之后。

软件包生态系统

注册表软件包版本月下载量版本数最近发布
npm@porulle/db0.10.41,409115 天前
npm@porulle/cli0.10.41,248115 天前
npm@porulle/sdk0.10.41,182115 天前
npm@porulle/core0.10.44,194115 天前
npm@porulle/jobs-inngest0.10.477865 天前
npm@porulle/jobs-pg-boss0.10.476665 天前
npm@porulle/jobs-trigger0.10.473865 天前
npm@porulle/jobs-cloudflare0.10.476365 天前

按类别列示的指标

活力

项目是否仍有生命——是否仍在编写代码,是否仍在发布版本?

74良好 · 占总体的 22%
评分方式
36/36推送新近度 — 最近一次推送于 5 天前
3.5/36提交节奏 — 52 周中有 5 周有提交
17.8/18提交量 — 最近一年 96 次提交
0/10OpenSSF Scorecard:Maintained — project was created within the last 90 days. Please review its contents carefully
所用输入
commits_last_year96
human_commit_share1
days_since_last_push5
active_weeks_last_year5

发布纪律

100优秀
评分方式
27/27有发布版本 — 已发布 2 个发布版本
36/36发布时效 — 最近一次发布版本于 39 天前
27/27发布节奏 — 约每 0 天发布一次
0/10OpenSSF Scorecard:Signed-Releases — 无数据
所用输入
releases_count2
latest_release_tagv0.6.0
releases_from_tags
days_since_latest_release39
mean_days_between_releases0
已排除计分(无数据或不适用):OpenSSF Scorecard:Signed-Releases。 其余权重已重新归一化。

社区与采用

项目是否拥有用户、下载量与关注度,并具备欢迎贡献者参与的配置?

35存在风险 · 占总体的 18%
评分方式
0/60星标 — 0 个星标
0/25复刻 — 0 个复刻
0/15关注者 — 0 位关注者
所用输入
forks0
stars0
watchers0
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history

社区健康

50中等
评分方式
22.5/22.5README
22.5/22.5许可证 — 可识别的许可证(MIT)
0/18CONTRIBUTING 指南
0/13.5行为准则
0/7.2议题模板
0/6.3PR 模板
所用输入
has_readme
has_license
has_contributing
has_issue_template
has_code_of_conduct
has_pull_request_template
评分方式
53.9/80月度下载量 — npm 合计每月 11,078 次下载
0/20注册表被依赖数 — 该生态系统不报告此项
所用输入
packages@porulle/db, @porulle/cli, @porulle/sdk, @porulle/core, @porulle/jobs-inngest, @porulle/jobs-pg-boss, @porulle/jobs-trigger, @porulle/jobs-cloudflare
dependents
ecosystemsnpm
total_downloads
monthly_downloads11,078
已排除计分(无数据或不适用):注册表被依赖数。 其余权重已重新归一化。

可持续性与治理

项目能否在其成员之外延续——巴士系数、响应能力、由谁支持,以及软件包的维护状况?

56中等 · 占总体的 24%
评分方式
9/54巴士系数 — 1 位贡献者贡献了半数提交
0/22.5提交分布 — 头号贡献者编写了 100% 的提交
1.4/13.5贡献者广度 — 1 位贡献者
3/10OpenSSF Scorecard:Contributors — project has 1 contributing companies or organizations -- score normalized to 3
所用输入
bus_factor1
contributors_sampled1
top_contributor_share1
评分方式
46.8/46.8议题解决 — 100% 的议题已关闭
38.2/38.3PR 接受 — 已裁定的 PR 中 13/13 已合并
0/15OpenSSF Scorecard:Code-Review — Found 0/13 approved changesets -- score normalized to 0
所用输入
merged_prs13
open_issues0
closed_issues55
issue_closed_ratio1
closed_unmerged_prs0
评分方式
30/30所有权背书 — 组织持有
0/20已验证域名
0/25所有者影响力 — asyncdotengineering 有 0 位关注者
13.8/25既往记录 — 9 个公开仓库,账户约 3 年
所用输入
followers0
owner_typeOrganization
is_verified
owner_loginasyncdotengineering
public_repos9
account_age_days1,197
评分方式
25/25已发布且可解析 — npm 上有 8 个软件包
35/35发布时效 — 最近一次发布于 5 天前
20/20版本历史 — 11 个已发布版本
20/20未被弃用 — 活跃,未被弃用或撤回
所用输入
packages@porulle/db, @porulle/cli, @porulle/sdk, @porulle/core, @porulle/jobs-inngest, @porulle/jobs-pg-boss, @porulle/jobs-trigger, @porulle/jobs-cloudflare
ecosystemsnpm
any_deprecated
min_days_since_publish5

工程质量

基础的工程与文档实践是否到位?

60中等 · 占总体的 20%

工程实践

40存在风险
评分方式
0/24CI 工作流
24/24存在测试
16/16Linter 配置 — eslint.config.js, eslint.config.mjs
0/9.6Pre-commit 钩子
0/6.4.editorconfig
0/20OpenSSF Scorecard:CI-Tests — 0 out of 9 merged PRs checked by a CI test -- score normalized to 0
所用输入
has_ci
has_tests
has_editorconfig
has_linter_config
has_precommit_config

文档

90优秀
评分方式
30/30README
25/25文档目录
15/15文档 / 主页站点 — https://porulle-docs.vercel.app
10/10仓库描述
0/10主题标签
10/10Wiki
所用输入
topics
has_wiki
homepagehttps://porulle-docs.vercel.app
has_readme
has_docs_dir
has_description

安全

可见的安全与供应链实践是否稳固,且不存在未解决的高风险司法辖区暴露?

37存在风险 · 占总体的 16%

安全态势

21危急
评分方式
7.5/7.5Binary-Artifacts — no binaries found in the repo
0/7.5Branch-Protection — branch protection not enabled on development/release branches
0/2.5CI-Tests — 0 out of 9 merged PRs checked by a CI test -- score normalized to 0
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
0/7.5Code-Review — Found 0/13 approved changesets -- score normalized to 0
0.8/2.5Contributors — project has 1 contributing companies or organizations -- score normalized to 3
0/10Dangerous-Workflow — 无数据
0/7.5Dependency-Update-Tool — no update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5许可证 — license file detected
0/7.5Maintained — project was created within the last 90 days. Please review its contents carefully
0/5Packaging — 无数据
0/5Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
0/5SAST — SAST tool is not run on all commits -- score normalized to 0
5/5Security-Policy — security policy file detected
0/7.5Signed-Releases — 无数据
0/7.5Token-Permissions — 无数据
0/7.5Vulnerabilities — 54 existing vulnerabilities detected
所用输入
sourceopenssf_scorecard
checks_evaluated14
scorecard_versionv5.5.0
checks_inconclusive4
scorecard_aggregate2.1
已排除计分(无数据或不适用):dangerous_workflow, packaging, signed_releases, token_permissions。 其余权重已重新归一化。
评分方式
35/35直接依赖不含已知公告 — 没有直接依赖携带已知公告
25/25间接依赖不含已知公告 — 没有间接依赖携带已知公告
0/40没有长期未处理的公告 — 没有公告带有发布日期
所用输入
sourceosv
advisories0
affected_packages0
assessed_packages57
unassessed_packages0
affected_by_severitynone
direct_affected_packages0
已排除计分(无数据或不适用):没有长期未处理的公告。 其余权重已重新归一化。 比对的是 npm:@porulle/db@0.10.4 的运行时依赖闭包——安装已发布的软件包时真正被拉取进来的内容——共 57 个软件包。 未对可达性进行分析。

AI 就绪度

该仓库在多大程度上具备与 AI 编码代理协同开发与维护的条件?这是一枚独立的实验性徽章——权重为 0.0,因此单独呈现,不影响总体健康评分。

69中等 · 占总体的 0%
评分方式
45/45代理指令 — .agents/factory/workers/claude.md, .archive/research/AGENTS.md, CLAUDE.md
0/15机器可读文档(llms.txt)
40/40可读的提交历史 — 96 次人类提交中有 96 次说明了意图(结构化标题或解释性正文)
所用输入
has_llms_txt
legible_history_share1
agent_instruction_files.agents/factory/workers/claude.md, .archive/research/AGENTS.md, CLAUDE.md
agent_instruction_max_bytes13,046
评分方式
0/18一条命令的引导启动
22/22自动化测试
11/11Lint / 格式化配置 — eslint.config.js, eslint.config.mjs
11/11静态类型检查 — apps/docs/public/scaffold/tsconfig.json, apps/docs/tsconfig.json, apps/restaurant-example/tsconfig.json, apps/saas-example/tsconfig.json, apps/store-example/tsconfig.json, apps/tea-avenue/tsconfig.json, apps/web/tsconfig.json, packages/adapters/adapter-local-storage/tsconfig.json, packages/adapters/adapter-meilisearch/tsconfig.json, packages/adapters/adapter-neon/tsconfig.json, packages/adapters/adapter-pg-search/tsconfig.json, packages/adapters/adapter-pglite/tsconfig.json, packages/adapters/adapter-postgres/tsconfig.json, packages/adapters/adapter-r2/tsconfig.json, packages/adapters/adapter-resend/tsconfig.json, packages/adapters/adapter-s3/tsconfig.json, packages/adapters/adapter-ses/tsconfig.json, packages/adapters/adapter-shopify/tsconfig.json, packages/adapters/adapter-stripe/tsconfig.json, packages/adapters/adapter-tax-manual/tsconfig.json, packages/adapters/adapter-taxjar/tsconfig.json, packages/adapters/adapter-woocommerce/tsconfig.json, packages/cli/templates/starter/tsconfig.json, packages/cli/tsconfig.json, packages/core/tsconfig.json, packages/db/tsconfig.json, packages/import/import-flat/tsconfig.json, packages/import/import-shopify/tsconfig.json, packages/import/import-woocommerce/tsconfig.json, packages/jobs-cloudflare/tsconfig.json, packages/jobs-inngest/tsconfig.json, packages/jobs-pg-boss/tsconfig.json, packages/jobs-trigger/tsconfig.json, packages/plugins/plugin-appointments/tsconfig.json, packages/plugins/plugin-channel-connector/tsconfig.json, packages/plugins/plugin-gift-cards/tsconfig.json, packages/plugins/plugin-layaway/tsconfig.json, packages/plugins/plugin-loyalty/tsconfig.json, packages/plugins/plugin-marketplace/tsconfig.json, packages/plugins/plugin-notifications/tsconfig.json, packages/plugins/plugin-pos-restaurant/tsconfig.json, packages/plugins/plugin-pos/tsconfig.json, packages/plugins/plugin-procurement/tsconfig.json, packages/plugins/plugin-production/tsconfig.json, packages/plugins/plugin-reviews/tsconfig.json, packages/plugins/plugin-scheduled-orders/tsconfig.json, packages/plugins/plugin-uom/tsconfig.json, packages/plugins/plugin-warehouse/tsconfig.json, packages/plugins/plugin-wishlist/tsconfig.json, packages/sdk/tsconfig.json
10/10可复现环境 — Dockerfile, lockfile
10/10已体现的代理实践 — 最近 96 次提交中有 73 次由代理编写或署名代理
0/8自动化维护 — 未观察到自动依赖更新
0/10OpenSSF Scorecard:Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
所用输入
has_nix
has_tests
lockfilespnpm-lock.yaml
has_dockerfile
typed_language
bootstrap_files
has_devcontainer
has_linter_config
typecheck_configsapps/docs/public/scaffold/tsconfig.json, apps/docs/tsconfig.json, apps/restaurant-example/tsconfig.json, apps/saas-example/tsconfig.json, apps/store-example/tsconfig.json, apps/tea-avenue/tsconfig.json, apps/web/tsconfig.json, packages/adapters/adapter-local-storage/tsconfig.json, packages/adapters/adapter-meilisearch/tsconfig.json, packages/adapters/adapter-neon/tsconfig.json, packages/adapters/adapter-pg-search/tsconfig.json, packages/adapters/adapter-pglite/tsconfig.json, packages/adapters/adapter-postgres/tsconfig.json, packages/adapters/adapter-r2/tsconfig.json, packages/adapters/adapter-resend/tsconfig.json, packages/adapters/adapter-s3/tsconfig.json, packages/adapters/adapter-ses/tsconfig.json, packages/adapters/adapter-shopify/tsconfig.json, packages/adapters/adapter-stripe/tsconfig.json, packages/adapters/adapter-tax-manual/tsconfig.json, packages/adapters/adapter-taxjar/tsconfig.json, packages/adapters/adapter-woocommerce/tsconfig.json, packages/cli/templates/starter/tsconfig.json, packages/cli/tsconfig.json, packages/core/tsconfig.json, packages/db/tsconfig.json, packages/import/import-flat/tsconfig.json, packages/import/import-shopify/tsconfig.json, packages/import/import-woocommerce/tsconfig.json, packages/jobs-cloudflare/tsconfig.json, packages/jobs-inngest/tsconfig.json, packages/jobs-pg-boss/tsconfig.json, packages/jobs-trigger/tsconfig.json, packages/plugins/plugin-appointments/tsconfig.json, packages/plugins/plugin-channel-connector/tsconfig.json, packages/plugins/plugin-gift-cards/tsconfig.json, packages/plugins/plugin-layaway/tsconfig.json, packages/plugins/plugin-loyalty/tsconfig.json, packages/plugins/plugin-marketplace/tsconfig.json, packages/plugins/plugin-notifications/tsconfig.json, packages/plugins/plugin-pos-restaurant/tsconfig.json, packages/plugins/plugin-pos/tsconfig.json, packages/plugins/plugin-procurement/tsconfig.json, packages/plugins/plugin-production/tsconfig.json, packages/plugins/plugin-reviews/tsconfig.json, packages/plugins/plugin-scheduled-orders/tsconfig.json, packages/plugins/plugin-uom/tsconfig.json, packages/plugins/plugin-warehouse/tsconfig.json, packages/plugins/plugin-wishlist/tsconfig.json, packages/sdk/tsconfig.json
agent_commit_share0.76
toolchain_manifests
dependency_bot_commit_share0
评分方式
45/45可类型检查的代码 — TypeScript(静态类型)
55/55可控的文件大小 — 采样的 804 个源文件中有 0 个超过 60KB
所用输入
primary_languageTypeScript
largest_source_bytes59,740
source_files_sampled804
oversized_source_files0
评分方式
0/40API 模式(OpenAPI/GraphQL/proto)
20/20MCP 服务器
0/40可运行示例
所用输入
example_dirs
has_mcp_signal
api_schema_files

关键数据

0GitHub 星标
1贡献者
96最近 12 个月提交数
5距最近推送天数
2发布版本数
1巴士系数(bus factor)
0开放议题
npm软件包生态系统数

数据采集警告

  • GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository

更多细节

OpenSSF Scorecard 2.1 / 10
2.1综合

来自开源项目 OpenSSF Scorecard 的独立、工具无关的安全评估。每项检查奖励的是安全实践本身,而非特定供应商的工具。Scorecard 无法判定的检查项标记为 不适用,并从安全评分中剔除(绝不按零分计)。Scorecard v5.5.0 · 2026-07-24 03:58 UTC

10Binary-Artifactsno binaries found in the repo
0Branch-Protectionbranch protection not enabled on development/release branches
0CI-Tests0 out of 9 merged PRs checked by a CI test -- score normalized to 0
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 0/13 approved changesets -- score normalized to 0
3Contributorsproject has 1 contributing companies or organizations -- score normalized to 3
不适用Dangerous-Workflowno workflows found
0Dependency-Update-Toolno update tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
0Maintainedproject was created within the last 90 days. Please review its contents carefully
不适用Packagingpackaging workflow not detected
0Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 0
0SASTSAST tool is not run on all commits -- score normalized to 0
10Security-Policysecurity policy file detected
不适用Signed-Releasesno releases found
不适用Token-PermissionsNo tokens found
0Vulnerabilities54 existing vulnerabilities detected
直接依赖 74
注册表软件包版本约束清单文件
npm@hono/node-server^1.14.3apps/restaurant-example/package.json
npm@porulle/adapter-local-storageworkspace:*apps/restaurant-example/package.json
npm@porulle/adapter-postgresworkspace:*apps/restaurant-example/package.json
npm@porulle/coreworkspace:*apps/restaurant-example/package.json
npm@porulle/plugin-posworkspace:*apps/restaurant-example/package.json
npm@porulle/plugin-pos-restaurantworkspace:*apps/restaurant-example/package.json
npm@porulle/plugin-uomworkspace:*apps/restaurant-example/package.json
npm@porulle/plugin-procurementworkspace:*apps/restaurant-example/package.json
npm@porulle/plugin-warehouseworkspace:*apps/restaurant-example/package.json
npm@porulle/plugin-productionworkspace:*apps/restaurant-example/package.json
npm@porulle/plugin-notificationsworkspace:*apps/restaurant-example/package.json
npm@porulle/plugin-scheduled-ordersworkspace:*apps/restaurant-example/package.json
npm@porulle/plugin-reviewsworkspace:*apps/restaurant-example/package.json
npmhono^4.12.5apps/restaurant-example/package.json
npm@hono/node-server^1.19.6apps/saas-example/package.json
npm@porulle/adapter-local-storageworkspace:*apps/saas-example/package.json
npm@porulle/adapter-postgresworkspace:*apps/saas-example/package.json
npm@porulle/coreworkspace:*apps/saas-example/package.json
npm@faker-js/faker^10.3.0apps/store-example/package.json
npm@hono/node-server^1.19.6apps/store-example/package.json
npm@hono/zod-openapi^1.2.2apps/store-example/package.json
npmhono^4.9.8apps/store-example/package.json
npm@porulle/adapter-local-storageworkspace:*apps/store-example/package.json
npm@porulle/adapter-postgresworkspace:*apps/store-example/package.json
npm@porulle/coreworkspace:*apps/store-example/package.json
npm@porulle/plugin-loyaltyworkspace:*apps/store-example/package.json
npm@porulle/plugin-wishlistworkspace:*apps/store-example/package.json
npm@porulle/plugin-reviewsworkspace:*apps/store-example/package.json
npm@hono/node-server^1.14.3apps/tea-avenue/package.json
npm@porulle/adapter-local-storageworkspace:*apps/tea-avenue/package.json
npm@porulle/adapter-postgresworkspace:*apps/tea-avenue/package.json
npm@porulle/coreworkspace:*apps/tea-avenue/package.json
npm@porulle/plugin-posworkspace:*apps/tea-avenue/package.json
npm@porulle/plugin-pos-restaurantworkspace:*apps/tea-avenue/package.json
npm@porulle/plugin-uomworkspace:*apps/tea-avenue/package.json
npm@porulle/plugin-procurementworkspace:*apps/tea-avenue/package.json
npm@porulle/plugin-warehouseworkspace:*apps/tea-avenue/package.json
npm@porulle/plugin-productionworkspace:*apps/tea-avenue/package.json
npm@porulle/plugin-loyaltyworkspace:*apps/tea-avenue/package.json
npm@porulle/plugin-notificationsworkspace:*apps/tea-avenue/package.json
npm@porulle/plugin-scheduled-ordersworkspace:*apps/tea-avenue/package.json
npm@porulle/plugin-reviewsworkspace:*apps/tea-avenue/package.json
npm@porulle/plugin-wishlistworkspace:*apps/tea-avenue/package.json
npmhono^4.12.5apps/tea-avenue/package.json
npmnext16.1.5apps/web/package.json
npmreact^19.2.0apps/web/package.json
npmreact-dom^19.2.0apps/web/package.json
npmpostgres^3.4.7packages/cli/package.json
npmcitty^0.1.6packages/cli/package.json
npmconsola^3.4.2packages/cli/package.json
npmgiget^2.0.0packages/cli/package.json
npm@better-auth/api-key^1.3.8packages/core/package.json
npm@better-auth/drizzle-adapter^1.3.8packages/core/package.json
npm@hono/zod-openapi^1.2.2packages/core/package.json
npm@scalar/hono-api-reference^0.10.5packages/core/package.json
npmbetter-auth^1.3.8packages/core/package.json
npmdrizzle-orm^0.45.1packages/core/package.json
npmdrizzle-zod^0.8.3packages/core/package.json
npmhono^4.9.8packages/core/package.json
npmhono-rate-limiter^0.5.3packages/core/package.json
npmpino^10.3.1packages/core/package.json
npmzod^4.1.11packages/core/package.json
npm@porulle/coreworkspace:*packages/db/package.json
npmdrizzle-orm^0.45.1packages/db/package.json
npmpostgres^3.4.7packages/db/package.json
npm@porulle/coreworkspace:*packages/jobs-cloudflare/package.json
npm@porulle/coreworkspace:*packages/jobs-inngest/package.json
npminngest^4.13.0packages/jobs-inngest/package.json
npm@porulle/coreworkspace:*packages/jobs-pg-boss/package.json
npmpg-boss^12.26.1packages/jobs-pg-boss/package.json
npm@porulle/coreworkspace:*packages/jobs-trigger/package.json
npm@trigger.dev/sdk^4.5.4packages/jobs-trigger/package.json
npmopenapi-fetch^0.17.0packages/sdk/package.json
npmopenapi-typescript-helpers^0.1.0packages/sdk/package.json
全部依赖 未采集

本报告未能采集到解析后的依赖集合:GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository

依赖安全公告 0

安装 npm:@porulle/db@0.10.4 会引入 57 个包(直接与传递):其中 0 个存在已知公告,0 个为直接依赖。

没有已知公告影响已评估的依赖。

公告表示依赖图中记录的版本落入某条公告的受影响范围。可达性未经分析,且依赖图包含开发与测试的版本固定——某项发现可能只涉及工具链而非交付的软件。

原始 JSON 报告 机器可读
{
  "data": {
    "repo": {
      "topics": [],
      "is_fork": false,
      "size_kb": 3150,
      "has_wiki": true,
      "homepage": "https://porulle-docs.vercel.app",
      "languages": {
        "CSS": 8195,
        "MDX": 521801,
        "Astro": 11184,
        "Shell": 31821,
        "Dockerfile": 1387,
        "JavaScript": 25805,
        "TypeScript": 3862923
      },
      "pushed_at": "2026-07-18T18:05:46Z",
      "created_at": "2026-05-11T21:13:08Z",
      "owner_type": "Organization",
      "updated_at": "2026-07-18T18:03:06Z",
      "description": "Headless commerce framework for TypeScript. REST-only, security-hardened, self-host-first. Active development, alpha — straight out of the oven.",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "MIT",
      "default_branch": "main",
      "license_spdx_raw": "MIT",
      "primary_language": "TypeScript",
      "significant_languages": [
        "TypeScript",
        "MDX"
      ]
    },
    "owner": {
      "blog": null,
      "name": "Asyncdot Engineering",
      "type": "Organization",
      "login": "asyncdotengineering",
      "company": null,
      "location": null,
      "followers": 0,
      "avatar_url": "https://avatars.githubusercontent.com/u/130723569?v=4",
      "created_at": "2023-04-14T02:52:53Z",
      "is_verified": null,
      "public_repos": 9,
      "account_age_days": 1197
    },
    "license": {
      "state": "standard",
      "spdx_id": "MIT",
      "raw_spdx": "MIT",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v0.6.0",
          "kind": "minor",
          "published_at": "2026-06-14T19:10:29Z"
        },
        {
          "tag": "v0.5.0",
          "kind": "minor",
          "published_at": "2026-06-14T18:16:21Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "017b18c2077d3e5401116ba6245b5b2d6183457e",
          "body": "* docs(audit): round-3 adversarial findings (kernel, math, plugins, schema)\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_0124euZZ7Qo6QyunCckprqA8\n\n* fix(core): capture full authorized amount, never record a $0 capture\n\nA full ca\n[…]\ne Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_0124euZZ7Qo6QyunCckprqA8\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(release): version packages to 0.10.4 (#85)",
          "author_name": "Mithushan Jalangan",
          "author_login": "octalpixel",
          "committed_at": "2026-07-18T18:03:01Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c6445828b4e8d4fb18ea7646a179997839f73030",
          "body": "chore(release): 0.10.3 — order quote engine + checkout tax composition fixes",
          "is_bot": false,
          "headline": "Merge pull request #84 from asyncdotengineering/chore/release-0.10.3",
          "author_name": "Mithushan Jalangan",
          "author_login": "octalpixel",
          "committed_at": "2026-07-18T15:47:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "da739df5cd7e1616115b4064d1c4ff845b9e17a9",
          "body": "Order quote engine (POST /api/orders/quote) + checkout tax composition fixes.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_0124euZZ7Qo6QyunCckprqA8",
          "is_bot": false,
          "headline": "chore(release): version packages to 0.10.3",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-18T15:46:44Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "a4f2fd53afaeb9e2f2fade6ae8a1c651479c7319",
          "body": "… D / audit C1,C2a)\n\nNew computeOrderPricing() runs the SAME pricing hooks checkout runs — resolve →\npromotions → shipping → tax — with no cart/inventory/payment side effects, so a\nmanual/draft order quote equals what checkout charges (single source, no drift).\nExposed as POST /api/orders/quote (ord\n[…]\napters still ignore orderDiscount — tracked for follow-up.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_0124euZZ7Qo6QyunCckprqA8",
          "is_bot": false,
          "headline": "feat(core): order pricing quote engine + tax composition fixes (Slice…",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-18T15:45:12Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "406404296b1aa20eb942c51eed9e55b137f832ad",
          "body": "…lugins)\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_0124euZZ7Qo6QyunCckprqA8",
          "is_bot": false,
          "headline": "docs(audit): round-2 adversarial findings (auth, async, supporting, p…",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-18T15:45:12Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "30118910a4bf197b75f0c2a50c4b53d0a935a397",
          "body": "…Vendure)\n\nSynthesis of an 8-agent parallel audit of the porulle engine. Verdict: primitives\nsound, composition mis-handles money. Convergent criticals (multi-agent + proven\nby porulle's own tests): tax computed before shipping (appliesToShipping dead),\nper-line discounts never attributed (tax over-\n[…]\ng.fulfillment. Full ranked findings + remediation roadmap.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_0124euZZ7Qo6QyunCckprqA8",
          "is_bot": false,
          "headline": "docs(audit): commerce-principles deviation report (vs Medusa/Shopify/…",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-18T15:28:41Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e111e0f069c26143d4a3682e4702709b43d7ef80",
          "body": "chore(release): 0.10.2 — promotions/validate returns authoritative cart discount",
          "is_bot": false,
          "headline": "Merge pull request #83 from asyncdotengineering/chore/release-0.10.2",
          "author_name": "Mithushan Jalangan",
          "author_login": "octalpixel",
          "committed_at": "2026-07-18T13:55:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6b6f340ea852feb9d9dc4dd580b2d8993b6f4f49",
          "body": "Patch: promotions/validate returns the authoritative cart discount (no client\nre-derivation → cart preview matches checkout).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_0124euZZ7Qo6QyunCckprqA8",
          "is_bot": false,
          "headline": "chore(release): version packages to 0.10.2",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-18T13:54:35Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "b920e7b19c2d2857ec0c8c90f42ef8abf1cbafda",
          "body": "POST /api/promotions/validate took the full cart context but returned only the\npromotion, forcing every consumer to re-derive the discount amount — which drifts\nfrom the computation checkout actually runs and shows customers a wrong number in\nthe cart vs at checkout. The route now calls promotions.a\n[…]\nrts a 10%\ncode on a 10000 cart returns totalDiscount 1000.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_0124euZZ7Qo6QyunCckprqA8",
          "is_bot": false,
          "headline": "fix(core): promotions/validate returns the authoritative cart discount",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-18T13:54:26Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f4119430993dcc3727a4ecdde25f8588c76b1fc1",
          "body": "chore(release): 0.10.1 — plugins work on zero-infra PGlite boot (U1)",
          "is_bot": false,
          "headline": "Merge pull request #82 from asyncdotengineering/chore/release-0.10.1",
          "author_name": "Mithushan Jalangan",
          "author_login": "octalpixel",
          "committed_at": "2026-07-18T12:46:04Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ad22182e70eebc0e158d8d43679e6a1f8d537a39",
          "body": "Patch: push merged plugin schema on zero-migration boot (U1) — @porulle plugins\n(gift cards, loyalty, …) now work on the zero-infra PGlite starter.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_0124euZZ7Qo6QyunCckprqA8",
          "is_bot": false,
          "headline": "chore(release): version packages to 0.10.1",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-18T12:44:44Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "f91d25216b5b2e422d59fa18fb30323d28b24e8d",
          "body": "… boot (U1)\n\nbuildSchema(config) — the only merge of plugin customSchemas into the schema —\nhad zero callers; pushSchema() pushed core-only getSchema(); nothing pushed the\nmerged schema at boot. Result: on a zero-migration (PGlite) boot, no plugin's\nown tables were ever created, so every plugin's ro\n[…]\now\nexists after createCommerce; migrate:false still skips.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_0124euZZ7Qo6QyunCckprqA8",
          "is_bot": false,
          "headline": "fix(core,adapter-pglite): push merged plugin schema on zero-migration…",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-18T12:33:16Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8ea14030836a121da1b82685c122bc190eada079",
          "body": "chore(release): version packages to 0.10.0",
          "is_bot": false,
          "headline": "Merge pull request #81 from asyncdotengineering/chore/release-0.10.0",
          "author_name": "Mithushan Jalangan",
          "author_login": "octalpixel",
          "committed_at": "2026-07-18T10:50:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3aac1cb20ef71d962459aadadfadd980be0b0569",
          "body": "Channel Connectors (Shopify/WooCommerce), cOAuth onboarding, app-level compliance\nwebhooks, job-engine hardening, security holistic-review follow-ups, and the new\n@porulle/adapter-pglite zero-infra database adapter.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_0124euZZ7Qo6QyunCckprqA8",
          "is_bot": false,
          "headline": "chore(release): version packages to 0.10.0",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-18T10:50:45Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "80ea718b2c730a17b89259dbc3caf2ff0552b4a1",
          "body": "…ter-prep\n\nfeat(adapter-pglite,docs): zero-infra PGlite adapter + docs overhaul + agent scaffold",
          "is_bot": false,
          "headline": "Merge pull request #80 from asyncdotengineering/feat/docs-pglite-star…",
          "author_name": "Mithushan Jalangan",
          "author_login": "octalpixel",
          "committed_at": "2026-07-18T10:46:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "efaf9d764aee10afabd02c0c511dda008d65a926",
          "body": "…(llms.txt, agent scaffold, light theme)\n\n- packages/adapters/adapter-pglite: new zero-infra DatabaseAdapter (embedded\n  WASM Postgres) — pushes core schema + seeds default org on boot; verified with\n  a real createServer boot test (GET /api/health → 200). Swap-compatible with\n  adapter-postgres. Id\n[…]\n.4.4 (6.4.6 dropped chunkToString and broke @astrojs/mdx).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_0124euZZ7Qo6QyunCckprqA8",
          "is_bot": false,
          "headline": "feat(adapter-pglite,docs): zero-infra PGlite adapter + docs overhaul …",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-18T10:45:54Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e3416fdcb9bec9efd136c3725d9584eab6a453f1",
          "body": "…-followups\n\nfix(core): security holistic-review follow-ups (R-03–R-07)",
          "is_bot": false,
          "headline": "Merge pull request #79 from asyncdotengineering/fix/security-holistic…",
          "author_name": "Mithushan Jalangan",
          "author_login": "octalpixel",
          "committed_at": "2026-07-18T08:16:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ff3d5e6e876f090119fd025aa6b5499f0dccd9fb",
          "body": "Low-severity hardening from the holistic review; none was a live exploit.\n\n- R-03 (SEC-12): orders/changeStatus discriminated a tolerable \"missing\n  inventory record\" by matching the message string. Add a typed\n  CommerceInventoryRecordNotFoundError (code INVENTORY_RECORD_NOT_FOUND) emitted\n  by the\n[…]\n: turbo test+check-types green — core 587 (+2), 1 skipped.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_0124euZZ7Qo6QyunCckprqA8",
          "is_bot": false,
          "headline": "fix(core): security holistic-review follow-ups R-03–R-07 (bf1f8053)",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-18T08:15:43Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "3d2f2ab116a69f477c8e0c33e6df88501b60729c",
          "body": "…ecret-and-redact-fanout\n\nfix(channel-connectors): Shopify webhook app-secret verification + compliance redact fan-out",
          "is_bot": false,
          "headline": "Merge pull request #78 from asyncdotengineering/fix/shopify-webhook-s…",
          "author_name": "Mithushan Jalangan",
          "author_login": "octalpixel",
          "committed_at": "2026-07-18T07:45:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "bcd6751050133d3546d303f4f9a6b95ad716530a",
          "body": "…shared shop_domain (d51ae76d)\n\nA shop_domain can map to multiple connected_stores rows (reconnect, or the same\nshop under two orgs). The compliance route resolved only the first via\ngetStoreByDomain, so a customers/redact / shop/redact erased PII on one store\nand left the others. Adds getStoresByDo\n[…]\npes green — plugin 40, core 585,\nadapters 6+6; docs build.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_0124euZZ7Qo6QyunCckprqA8",
          "is_bot": false,
          "headline": "fix(plugin-channel-connector): fan out compliance redaction across a …",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-18T07:45:09Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "92284bb44b019ffb95e751a028e58d941ec26fb3",
          "body": "…2380508c)\n\nShopify signs every webhook for an app with the app client/API secret key —\nthere is no per-store secret (unlike WooCommerce). verifyWebhook was checking\nagainst store.webhookSecret (a random uuid), so real Shopify sync-webhook\ndeliveries would fail HMAC verification; offline tests only \n[…]\nerified: turbo test+check-types green (adapter-shopify 6).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_0124euZZ7Qo6QyunCckprqA8",
          "is_bot": false,
          "headline": "fix(adapter-shopify): verify webhooks against the app client secret (…",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-18T07:44:54Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "55826cac7a3e56a8446517b2c81f221357b4931c",
          "body": "feat: Channel Connectors — Shopify/WooCommerce connectors, OAuth onboarding + compliance",
          "is_bot": false,
          "headline": "Merge pull request #77 from asyncdotengineering/feat/channel-connectors",
          "author_name": "Mithushan Jalangan",
          "author_login": "octalpixel",
          "committed_at": "2026-07-18T07:34:48Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "aa63b4266253f14727070711a9427830201176b6",
          "body": "… (c3e5dcf5)\n\nThe mandatory GDPR webhooks (customers/data_request, customers/redact,\nshop/redact) are delivered to a single app-level URL, signed with the app\nclient secret, and route by shop_domain in the payload — not per-store. The\nfirst pass wired the (correct) redaction logic to the per-store w\n[…]\n 39,\nadapter-shopify 6, adapter-woocommerce 6; docs build.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_0124euZZ7Qo6QyunCckprqA8",
          "is_bot": false,
          "headline": "fix(channel-connectors): app-level Shopify compliance webhook ingress…",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-18T07:13:12Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8f8c564deb399a86c50d27d8ca07e5334888bf30",
          "body": "… compliance redaction groundwork\n\nAdds a second onboarding front door alongside credential-paste, converging on\nthe same connectStore pipeline (no store mode flag, no engine branching):\n\n- core: ChannelConnector gains optional buildAuthUrl + completeAuth\n- plugin: generic /api/channels/oauth/{provi\n[…]\n adapter-shopify (6), adapter-woocommerce (6); docs build.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_0124euZZ7Qo6QyunCckprqA8",
          "is_bot": false,
          "headline": "feat(channel-connectors): one-click OAuth store onboarding (cOAuth) +…",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-18T06:59:32Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "22e0be4eca991f78aed7f458306a399c9dc7c8ce",
          "body": "…engine hardening\n\nConnect external Shopify/WooCommerce stores, mirror catalog/inventory, sell through\none checkout, and inject paid orders back into the merchant's store. Standalone\nengine plugin + thin provider adapters, on the hardened order/refund core.\n\ncore:\n- sellable_entities.sourceStoreId p\n[…]\ntore-connector guide,\nreference/jobs + reference/adapters.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_0124euZZ7Qo6QyunCckprqA8",
          "is_bot": false,
          "headline": "feat(channel-connectors): Shopify/WooCommerce store connectors + job-…",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-18T04:19:38Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "96da7640663ed952f2f1abd9d0ec52862b341117",
          "body": "…tners to the private board\n\nWire Plan Desk into the repo and move two in-design features off public\nGitHub issues into the local Plan Desk board (project Porulle).\n\n- Setup: .mcp.json (MCP server), .plandesk/ (config, skill, workspace.db board),\n  .agents/ + .codex/ factory+curator policy, CLAUDE.m\n[…]\nssues #60-76 deleted; both features now tracked privately.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_0124euZZ7Qo6QyunCckprqA8",
          "is_bot": false,
          "headline": "chore(plandesk): set up Plan Desk and migrate channel-connector + par…",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-16T04:16:23Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4dfa8beb5cb3957418f5b2b7b28c35eadd55f288",
          "body": "Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_0124euZZ7Qo6QyunCckprqA8",
          "is_bot": false,
          "headline": "chore(release): version packages to 0.9.0",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-15T06:52:21Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "0d45e95eeb022adcd1162735d3d9a9ebf70411b7",
          "body": "A creative red-team (deepseek-v4-pro) found that refundLines was never audited\nfor interplay with changeStatus refunds, the order lifecycle, and the payment\nlayer. The two refund paths tracked cumulative refunds independently. Fixes in\nOrderService:\n\n- R-01 (Critical) double payout: changeStatus(\"re\n[…]\ning) — no raw SQL / `as any`.\nturbo run test: 55/55 green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_0124euZZ7Qo6QyunCckprqA8",
          "is_bot": false,
          "headline": "fix(security): close refund money-conservation cluster (deepseek VAPT)",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-15T06:35:05Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4c94f20075d6417934c4d5beda763768ea738867",
          "body": "…ut IDOR, gift-card tenancy\n\nA CVE-class VAPT (kimi-k2.7, real Postgres) proved 9 exploitable defects. Fixes:\n\n- Inventory broken-access-control (Critical/High): /api/inventory/warehouses,\n  /reserve, /release had no authorization — a customer could configure warehouses\n  and reserve/release stock, \n[…]\nd). kimi harness: 24 checks, 0 broken; turbo: 55/55 green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_0124euZZ7Qo6QyunCckprqA8",
          "is_bot": false,
          "headline": "fix(security): close VAPT CVE-class cluster — inventory authz, checko…",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-15T05:58:17Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d8c77db7634a1a4b58517cecaeedd16705b22094",
          "body": "…t integrity, provenance\n\nA blind VAPT against a real Postgres instance proved two exploitable defects on\nthe order-creation surface, reachable by a customer-role actor over POST /api/orders:\n- money integrity: the primitive persisted client-supplied unitPrice/grandTotal\n  verbatim, so a customer cr\n[…]\n 55/55 green; real-Postgres hostile-path\nmatrix: 8/8 safe.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_0124euZZ7Qo6QyunCckprqA8",
          "is_bot": false,
          "headline": "fix(security): harden order creation — server-price by default, tenan…",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-15T04:56:28Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "beaf78acbcc8dc9a164ac051cc2db95b806b5dac",
          "body": "…2 (SEC-18)\n\nR-01 (Critical) — pin-login granted the operator an org `owner` membership on\nevery login (cashier -> owner escalation) because better-auth's\nreferences:\"organization\" key requires owner/admin to mint. Reworked: mint a\nUSER-referenced key that carries the operator's store in metadata (n\n[…]\n guard to both routes; regression test\nproves an admin cannot demote or revoke an owner.\n\nplugin-pos green (44), core green (552).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(security): resolve holistic-review blockers R-01 (SEC-16) and R-0…",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-14T15:46:56Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "50146cd204afaa76fd483267b79551ce01a69899",
          "body": "Add pos_pin_attempts table and lockout logic in verifyOperatorPin:\nafter 5 failed attempts within 15 minutes, block further PIN verification\nfor that operator until lockout expires. Counter resets on success.\nConfigurable via pinAuth.lockoutMaxAttempts and lockoutWindowMinutes.",
          "is_bot": false,
          "headline": "feat(pos): SEC-15 per-operator PIN brute-force lockout",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-14T15:02:17Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3757e48006ecb8dc14f0cbf3f568a3f93646c3e2",
          "body": "…eanup\n\nSEC-17: validate timeDimensions against cube schema and build SELECT\naliases from canonical cube.member names instead of raw user strings.\n\nSEC-20: forward each stale order's organizationId via a system actor so\ncancel operates in the correct org instead of defaulting to org_default.\n\nRegression tests in packages/core/test/issue-SEC-17-* and issue-SEC-20-*.",
          "is_bot": false,
          "headline": "fix(security): SEC-17 analytics alias safety, SEC-20 per-org stale cl…",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-14T14:01:15Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e9ab029ac737cda08933be0645f32155444fb520",
          "body": "…t-in, pg-only\n\nSEC-18: Reject role assignments above the actor's privilege rank in\ncreateStaff and updateStaffRole (owner > admin > custom).\nSEC-19: Require config.auth.allowTestActor in addition to NODE_ENV=test\nfor x-test-actor header injection; enabled in test harness.\nSEC-05: Remove dead mysql/sqlite branches from auth/setup.ts.",
          "is_bot": false,
          "headline": "fix(security): SEC-18/19/05 auth hardening — role rank, test-actor op…",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-14T13:47:54Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6aa0c0fc365de56e0589ed25391e6af1126b1a1d",
          "body": "… SEC-04)\n\nChild tables now emit UNIQUE (col) instead of silently dropping unique: true.\nTop-level tables keep per-org UNIQUE (organization_id, col) for unique: true;\nunique: \"global\" renders UNIQUE (col). Docstrings corrected.",
          "is_bot": false,
          "headline": "fix(db): honor child-table unique + add global unique opt-in (SEC-03,…",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-14T13:38:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d05a170c19457eedc28fb36261b3dcb3b866b44f",
          "body": "…stomer\n\nThe checkout handler resolved a client-supplied customerId via getById/getByUserId\nwith no check that it belongs to the actor, so an authenticated customer could\nattribute an order to another customer. Extract resolveCheckoutCustomerUuid: a\nself-service actor only ever resolves to its OWN p\n[…]\ntomers:read. Guests\nunchanged. Helper is unit-tested (customer blocked, own honored, staff allowed).\n\nFull core suite green (545).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(core): SEC-07 don't let checkout attribute an order to another cu…",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-14T13:36:29Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d0c9cf70c63d3dd665ebbf04aed3ab19760b24ad",
          "body": "Thread organization_id through recipe-deduction raw SQL fallback (INSERT +\nUPDATE predicates) and add defense-in-depth org predicates to POS shift/txn\ncounters, loyalty redemption increments, and KDS ticket numbering. Add\nregression test proving inventory_movements inserts succeed and cross-org\ninventory_levels rows are untouched.",
          "is_bot": false,
          "headline": "fix(security): close tenant-scoping gaps in raw SQL writes (SEC-raw-sql)",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-14T13:25:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "34b6e6edd1234969d8c105260b952bad7a7a5646",
          "body": "Cancel/refund and fulfillment paths now release stock in the order's\norg and propagate real release failures. Add regression test for org-B\ncancel without creating a default-org warehouse.",
          "is_bot": false,
          "headline": "fix(SEC-12): pass actor/ctx into changeStatus inventory.release",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-14T13:13:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4f21bead99cbacfadecf090a9c6d19cf33a13237",
          "body": "Reject cross-tenant GRN create attempts before any PO item updates.\nAdd regression test proving org-B quantity_received stays unchanged.",
          "is_bot": false,
          "headline": "fix(SEC-21): validate GRN poId/poItemId belong to actor org",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-14T13:13:15Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "820ec6ea59b8c883105a5cee048168a04c33a98f",
          "body": "…the client\n\nPOST /pos/returns took items[].refundAmount straight from the body with no FK,\nno cap, no ledger and no idempotency — any cashier could complete a fabricated,\nunbounded cash refund against a foreign/fake order. Route the return through\norders.refundLines (the primitive the exchange flow\n[…]\nvers: server-derived amount, fabricated order rejected,\nover-refund rejected, double-refund rejected. plugin-pos suite green (42).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(plugin-pos): SEC-08 derive POS return refund from the order, not …",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-14T13:00:02Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "49db99dcd2c7e8ee61b51cbf6d7278ab08dba985",
          "body": "Pass organizationId when minting shift credentials, register the POS\nscope with references:organization, wire Better Auth config forwarding,\nand resolve org-owned keys in auth middleware. Ensures operator org\nmembership before minting and adds a multi-org regression test.",
          "is_bot": false,
          "headline": "fix(SEC-16): bind pin-login API keys to operator organization",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-14T12:48:02Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6c3f01608be9b9c378c5e45a5a655f3e587dc106",
          "body": "Exchange replacement lines now use pricing.resolve() per entity/variant\ninside the atomic transaction; client unitPrice is ignored. Adds a\nregression test and seeds catalog prices in exchanges.test.ts.",
          "is_bot": false,
          "headline": "fix(SEC-14): resolve exchange replacement prices server-side",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-14T12:47:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d4fafeb66aaeed57478ddf021795925599e2a385",
          "body": "cart.addItem, pricing.setBasePrice and pricing.resolve fetched the entity via\nfindEntityById WITHOUT the actor's org, so another tenant's entity id could be\nadded to a cart or have a price stamped against it. Pass the resolved orgId so\nthe lookup is org-scoped (cross-org id -> not found). routes/pri\n[…]\ng.calculator) operate on already-org-resolved ids; making orgId globally\nrequired there is a follow-up (see IMPLEMENTATION-NOTES).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(core): SEC-10 scope user-facing findEntityById lookups by org",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-14T12:29:02Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "3f0cd4870df9f88e55c3d129910a87901d43115d",
          "body": "Adds a regression test proving anonymous storefront reads are scoped to the\nrequest's store: an org-bearing anonymous actor (as storeResolver middleware\nsets) reads its own store's product but not another store's. Confirms the\nSlice-2 getById fix is store-aware (kimi WBS R-03); no resolveOrgId change is\nneeded — the storeResolver already carries the store org.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "test(core): SEC-11 lock multi-store anonymous read isolation",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-14T12:22:01Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "dc2d119fa20cb1b31db114e5eb435fc59f233246",
          "body": "createScopedDb previously intercepted only insert/select; update and delete\npassed through unscoped, so a scoped write filtered by a business key reached\nevery tenant (proven live against Postgres). Intercept update() and delete()\ntoo: pre-apply the org predicate (so a no-WHERE write can't sweep oth\n[…]\n.\n\nRegression test covers update/delete by business key across two orgs and the\nno-WHERE case. Full core suite green (537 passed).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(core): SEC-01 scope UPDATE/DELETE in the scoped-db proxy",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-14T12:02:13Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e206941c832c86e3cbd0417763d06f8682aba434",
          "body": "…tion",
          "is_bot": false,
          "headline": "test(core): SEC-11 regression for anonymous catalog getById org isola…",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-14T10:56:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5328bf856614f351ede9039b02e8b3982598da84",
          "body": "…tions",
          "is_bot": false,
          "headline": "fix(core): SEC-09 assert org ownership on catalog option/variant muta…",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-14T10:56:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4a11eb4cfa3decb63e4ec5ac0b2aba8098f02407",
          "body": null,
          "is_bot": false,
          "headline": "fix(core): SEC-06 require customers:update on CustomerService.update",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-14T10:56:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "48d9eea33582b04bb7fc0b6fcad50cafad7b49ad",
          "body": "Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(plugin-layaway): add package README",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-02T16:36:41Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "2c80a39139bf5f2709a0b5c417e0c195fca6c8d5",
          "body": "New guides (building/): Store Settings, Receipts & Invoices, Tax Classes,\nRefunds & Exchanges, Layaway. Extended POS (PIN auth, order notes/timeline)\nand Analytics (retail reports) guides, the SDK guide (OfflineQueue), and the\nplugin contract (contributing api-key scopes). Reference updates: new\nend\n[…]\nthe v0.8.0 changelog entry and registered the new pages in the sidebar.\n\nVerified: astro build green (59 pages), all 271 internal links resolve.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: document the 0.8.0 retail-operations surface",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-02T16:30:09Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a52069c1c55372b629c43d33d8a5b58271ab7c2c",
          "body": "Consumes 6 changesets (admin/operator gaps #40–#46, ordereka field-study\nbatches #47–#59, integrator quick wins) into the fixed @porulle/* line:\n0.7.0 → 0.8.0. plugin-layaway and adapter-neon join at 0.8.0.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(release): version packages to 0.8.0",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-02T16:13:00Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "ae7c329c8e6a40aa5a6a23141e909e6925339c45",
          "body": "…yaway plugin, migration guide (#56–#59)\n\nFinal batch of the ordereka field-study roadmap.\n\n- #56 Order notes + activity timeline: POST/GET/DELETE /api/orders/{id}/notes\n  (author, pinned-first ordering; new order_notes table) and\n  GET /api/orders/{id}/timeline — one merged view of status history, \n[…]\n forfeit + reservation\nrollback). Full repo green (55/55 turbo test tasks), typecheck 38/38,\nbuild 36/36, lint clean, drizzle drift check clean.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(core,plugin-layaway,docs): order notes/timeline, tax classes, la…",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-02T10:01:21Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f40b3d1c624cfd5936086837074ee4c79ebbe5e7",
          "body": "…1–#53)\n\nBatch three of the ordereka field-study roadmap.\n\n- #52 Core refund policy primitives: order_line_items.refunded_quantity is a\n  real column enforced by POST /api/orders/{id}/refunds (per-line refundable\n  quantity, 422 on over-refund); an optional per-operator daily cap read from\n  setting\n[…]\npos pin-auth (4) + exchanges (3).\nFull repo green (54/54 turbo test tasks), typecheck 37/37, build 35/35,\nlint clean, drizzle drift check clean.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(core,plugin-pos): refund policy, PIN auth runtime, exchanges (#5…",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-02T09:39:21Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "df61d25c01130dc182545edd65efacd61bd89c16",
          "body": "…er (#54, #55)\n\nBatch two of the ordereka field-study roadmap.\n\n- #54 @porulle/sdk OfflineQueue: persistent operation queue for POS clients\n  that must sell through network drops. Pluggable storage (memoryStorage /\n  webStorage for anything localStorage-shaped), idempotencyKey stamped into\n  every b\n[…]\non (6 — fresh-pool-per-tx incl. throw path, Hyperdrive routing,\nexecute shape). check-types/lint/test green for both packages; repo build\ngreen.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(sdk,adapter-neon): offline sale queue + Workers-grade Neon adapt…",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-02T09:02:55Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "157221c9fad2a6190b691878aee4fc95edebe0fe",
          "body": "…e-call variants (#47–#50)\n\nBatch one of the ordereka field-study roadmap (first production adopter;\nevidence in .understanding/ordereka-porulle-usage.md).\n\n- #49 Settings: org-scoped runtime settings module — typed groups (general/\n  branding/policies, custom groups allowed) with shallow-merge PATC\n[…]\n7→19.\nFull repo green (54/54 turbo test tasks; core 514 passed, 1 skipped),\ntypecheck 36/36, build 35/35, lint clean, drizzle drift check clean.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(core): retail operations pack — settings, documents, reports, on…",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-02T08:58:48Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "230f405b9160c86f2626a900691bdc16444b73e1",
          "body": "…c requirePerm, order/checkout idempotency\n\nFindings from studying ordereka-fashion-pos (first production adopter,\npinned to @porulle/core 0.1.0). Full evidence-grounded map committed at\n.understanding/ordereka-porulle-usage.md; remaining reconciled gaps filed\nas issues #47–#59.\n\n- config.routes(app\n[…]\nment-adapter\ncall-count proof). Full core suite green (494 passed, 1 skipped, 94 files);\ntypecheck clean; lint clean; drizzle drift check clean.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(core): ordereka field-study quick wins — auth in routes(), publi…",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-01T23:07:52Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5c580c46bf9769e30e3a305ee74c1881c55cdf3f",
          "body": "Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: changeset for admin/operator API gap fixes (#40–#46)",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-01T22:35:28Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "8849231abbad6399046b48477cf8a1c0f57db11a",
          "body": "Seven issues found while operating a store against @porulle/core 0.7.0.\n\n- #40 Fulfillment: POST /orders/{id}/fulfillments records a shipment for a\n  subset of line items with carrier/trackingNumber/trackingUrl; supports\n  partial + multiple fulfillments, validates against over-fulfillment, and\n  re\n[…]\nsts). Full repo green\n(53/53 turbo test tasks; core 501 passed, 1 skipped), typecheck 36/36,\nbuild 34/34, lint clean, drizzle drift check clean.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: resolve admin/operator API gaps (#40–#46)",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-01T22:34:06Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "fccd499054b0be7671b7d210c520dac932b7a993",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): version packages 0.7.0",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-01T19:52:31Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f2c20ec6ca43c5691a4794e2dbd45b065ca774c4",
          "body": "fix: resolve admin-panel API gaps (#33–#38)",
          "is_bot": false,
          "headline": "Merge pull request #39 from asyncdotengineering/fix/triage-issues-33-38",
          "author_name": "Mithushan Jalangan",
          "author_login": "octalpixel",
          "committed_at": "2026-07-01T19:50:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5dd324bc4a39d56a5c3b7daa07ee7e7453ba9abb",
          "body": "Six issues found while building an admin panel against @porulle/core 0.6.0.\n\n- #33 Pricing: setBasePrice now upserts on the natural key instead of\n  inserting a duplicate shadow row; ?include=pricing exposes id + createdAt\n  so consumers can disambiguate the authoritative row.\n- #34 CSRF: the global\n[…]\nref.\n\nTests: 5 new issue regression suites (13 tests). Full core suite green\n(464 passed, 1 skipped); typecheck 36/36; lint clean.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: resolve admin-panel API gaps (#33–#38)",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-07-01T17:02:33Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "332bd17feab9d4fe0259035a0af8a04c24bca422",
          "body": "Cut by `changeset version`. Fixed @porulle/* group → 0.6.0; per-package\nCHANGELOGs generated. Headline change: fix(cli) scaffold version pinning (#32).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(release): version packages 0.6.0",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-06-14T19:08:36Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "dcc4fe98a476ae91d12a13495db20fe2e7d5dd2e",
          "body": "The starter template carried static `^0.5.0` ranges that never tracked\nreleases; under 0.x caret semantics a project scaffolded by a newer CLI\nresolved a full minor behind. `init` now reads the running CLI's version\n(the @porulle/* fixed group's shared version) and rewrites every\n@porulle/* dependency in the scaffolded package.json to `^<that version>`.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(cli): pin scaffolded @porulle/* deps to the CLI's own version (#32)",
          "author_name": "Mithushan Jalangan",
          "author_login": "octalpixel",
          "committed_at": "2026-06-14T19:07:00Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "9915af04e41fad265c73d55416b6331a10143fcb",
          "body": "pnpm strips the workspace: protocol to the depended-on package's *current*\npackage.json version at publish (workspace:* → 0.5.0), so internal deps can\nuse the workspace:* convention without the npm-leak (#24) or stale-lockfile\nfailure modes bun hit. Verified: pnpm pack of adapter-r2 emits\n\"@porulle/\n[…]\nEASING.md updated for pnpm.\n\nVerified under pnpm: check-types 36/36, build 34/34, core tests 451/1,\nfrozen-lockfile install clean.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(release): migrate package manager bun → pnpm (#31)",
          "author_name": "Mithushan Jalangan",
          "author_login": "octalpixel",
          "committed_at": "2026-06-14T18:51:45Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "33a041b56bf2e7af670f2d25837b1873da66ec0c",
          "body": "- release script: build filter ./packages/* → ./packages/** (the old filter\n  matched only the 4 top-level packages and silently skipped every nested\n  adapter/plugin/import, which would publish without a fresh dist). Also\n  append `git push --follow-tags`.\n- version-packages: run `bun install` afte\n[…]\ne:; bun publish strips from a stale\n  lockfile — both reproduced), the changeset version→publish flow, and the\n  pnpm alternative.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(release): fix release scripts + document the proper flow",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-06-14T18:25:43Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d6c2f16efb82d07bdf07df9cd513d61a8972775a",
          "body": "- Bump all @porulle/* publishable packages 0.1.0 → 0.5.0 (fixed-version group).\n- Rewrite internal @porulle/* deps (workspace:* / ^0.1.0 → ^0.5.0) so published\n  manifests carry real ranges, not the workspace protocol npm can't resolve\n  (the #24 class of bug). Includes the cli starter template.\n- CHANGELOG 0.5.0 entry; README de-alpha → beta (badge, tagline, Status).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release: 0.5.0 — out of alpha",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-06-14T18:04:35Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "8e72faf5325eedbe62286b35283c0ab02f1b6226",
          "body": "Close all 29 open issues + monorepo green sweep",
          "is_bot": false,
          "headline": "Merge pull request #30 from asyncdotengineering/triage/close-all-issues",
          "author_name": "Mithushan Jalangan",
          "author_login": "octalpixel",
          "committed_at": "2026-06-14T17:52:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b2ec7d9922a59b00100d1b88485c8f183e8df3f2",
          "body": "Under a full-monorepo `turbo run test`, ~6 PGlite (WASM Postgres) suites run\nin parallel and contend for CPU/memory, so a couple of core tests\nintermittently exceeded the 10s testTimeout (they finish in ~1-2s run alone,\nand the standalone core suite is consistently 451/1). The schema-push\nhookTimeou\n[…]\nder load. Not masking a perf regression — every affected test\npasses in isolation.\n\nAfter: full `turbo run test` is green (53/53).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "test(core): raise testTimeout to 30s for parallel-CI PGlite contention",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-06-14T17:47:16Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "89967f54e83d253170e86d2375be36a7394e9276",
          "body": "…ripts\n\nseed.ts and full-flow.ts called catalog.addToCategory/addToBrand with only\n(entityId, categoryId) — but both require the authenticated actor as the 3rd\narg for the catalog:update permission check + org-scoping. Both scripts\nalready pass `staff` to every other catalog mutation (createCategory\n[…]\no\n`turbo run check-types` (the vitest gate doesn't type-check app scripts).\n\nAfter: the entire monorepo type-checks clean (36/36).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(store-example): pass actor to addToCategory/addToBrand in seed sc…",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-06-14T17:39:10Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e8e251d053e9311b0fe8f42cab940c576b76eaae",
          "body": "…ter (#12, #28)\n\nDocument the Workers deploy path end to end, tying together the seams that\nalready ship in @porulle/core:\n\n- #12: lazy per-isolate boot — build the config from env inside fetch() and\n  memoize the server per isolate (createServer().runJobs() wired into\n  scheduled()); BETTER_AUTH_SE\n[…]\nr\nhelpers are documented as recipes; the underlying config seams are all\nfirst-class, so no framework monkey-patching is required.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: Cloudflare Workers deploy recipe — lazy config + env-aware adap…",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-06-14T17:23:48Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "3d52e924d29275f679d85bf610cd10e6197c781b",
          "body": "Capture the five day-one principles that prevent the most common app\nfoot-guns: cast-ban (parseJson), audit-on-mutation (auditMiddleware), no\nsilent money clamping, contract-named tests, and a single field-mappable\nerror envelope (err + mapApiErrorToFields). Each rule has a rationale, a\ncode example against the real @porulle/core / @porulle/sdk exports, and the\ncopy-pasteable cast-ban CI guard script. Linked from the README.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: day-one principles for Porulle apps (#19)",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-06-14T17:23:37Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d2d5e010356cb6bd3aa7b507e378bdb5148b85cf",
          "body": "The api-key create command already mints a long-lived key in-process (boots\nthe kernel, calls auth.api.createApiKey). Round it out to the make-key spec:\n\n- --ttl <seconds> → expiresIn, rejecting values below Better Auth's 1-day\n  minExpiresIn with a clear message.\n- --user <id> → bind the key to a s\n[…]\n\n  copy it now' note.\n\n(The command is , the CLI's canonical in-process\nkey minter — the make-key capability the issue describes.)\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(cli): make-key flags (--ttl, --user) + curl/revoke output (#18)",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-06-14T17:21:14Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e7865f4663974eb3d46c13b7420c79e842099038",
          "body": "No way to record non-transactional customer interactions (visits, calls,\ninquiries, fittings, follow-ups) — the data that powers clienteling.\n\n- Schema: customer_interactions (org-scoped, customer_id FK cascade,\n  actor_user_id, kind, notes, related_entity_id, metadata jsonb, at) +\n  indexes. Auto-i\n[…]\n create → list → edit → delete round-trip; invalid kind rejected.\nFull core suite green (81 files / 451 passed); type-check clean.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(core): customer interaction log (clienteling notes) (#3)",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-06-14T17:19:49Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "efe386a36272e09fde7bae9fdd5472897d972b3f",
          "body": "…on (#5)\n\nPOS walk-ins have no Better Auth user, but the customer schema requires a\nuserId — forcing every integration to mint synthetic walk_* users.\n\n- CustomerService.createWalkIn(): userId is optional; when omitted, a\n  synthetic anonymous_<uuid> id is generated and metadata.walkIn is set to\n  t\n[…]\nta.walkIn=true;\ncreate with userId → bound to it, no walkIn flag. Full core suite green\n(80 files / 449 passed); type-check clean.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(core): POST /api/customers supports walk-in / userId-less creati…",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-06-14T17:12:39Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "527c2b9507f84a71f01d05fac326133a01f994ae",
          "body": "Categories had no status column, so consumers hacked metadata.archived;\nhard DELETE cascades entity_categories (products silently lose their\ncategory).\n\n- Schema: categories.status text NOT NULL DEFAULT 'active' (active|archived).\n  Backwards-compatible — existing rows default to 'active'.\n- Categor\n[…]\n; DELETE works for\ncatalog:update; archive 403 without the scope. Full core suite green\n(79 files / 447 passed); type-check clean.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(core): category status + archive/restore endpoints (#22)",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-06-14T17:08:37Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f0e1ddb0e9ac385d88f5a0410ea9f081fc191e09",
          "body": "defineConfig already accepts ANY DatabaseAdapter (config.databaseAdapter),\nkernel.database.db is the generic adapter type (unknown — not pinned to\npostgres-js), and the PGlite adapter (a non-postgres-js driver) is injected\nacross the whole suite. Pin the contract with an explicit test: inject a\ncustom adapter, assert the kernel uses it (provider + driver flow through).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "test(core): pin custom DatabaseAdapter injection (#10)",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-06-14T17:01:51Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "fa2aac76b27ffcdfd03be8c53b2e735a3fa76089",
          "body": "The job-runner tick existed internally but wasn't reachable, so Workers\n(where in-process setInterval can't outlive a request) had no clean way to\ndrive the queue from scheduled().\n\n- createServer now returns runJobs(queue?, limit?), which runs the stale-job\n  reaper then one runPendingJobs() pass a\n[…]\nr().runJobs() is callable and returns a processed/failed\nsummary. Full core suite green (77 files / 442 passed); type-check clean.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(core): expose server.runJobs() for serverless cron (#15)",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-06-14T17:00:09Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ccada832952caecd7b6aa67720e7cc1a16d9b28e",
          "body": "On Workers/edge, c.req.raw.socket.remoteAddress is always undefined, so\nevery client collapsed onto the rate-limit key 'unknown' — sharing one\nbucket globally (trivially DoS-able).\n\n- defineConfig({ runtime: { getClientIp, trustedProxyIp } }). The internal\n  rate limiter resolves the client IP via c\n[…]\ne socket; X-Forwarded-For trusted only from the configured proxy.\nFull core suite green (76 files / 441 passed); type-check clean.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(core): injectable runtime.getClientIp for edge runtimes (#13)",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-06-14T16:57:31Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b41a36b41e370694b2f2cc9c455ddf2b6cf15379",
          "body": "Raw-SQL code that destructured db.execute(sql`...`) as an array worked on\npostgres-js but broke on neon-http / node-postgres / PGlite, which return\n{ rows, command, rowCount }.\n\n- createDatabaseConnection now wraps the adapter db (and transaction\n  handles) in a Proxy that makes execute() always ret\n[…]\n keep their this-binding; unwrapDb round-trips to the raw driver.\nFull core suite green (75 files / 438 passed); type-check clean.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(core): normalize db.execute() result shape across drivers (#11)",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-06-14T16:54:07Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "18512df3441c6e818489daaaa090a8b7f3c42e4f",
          "body": "Receipt-less returns / support couldn't find an order from a phone or\nlast name. Add a fuzzy lookup that joins orders + customers.\n\n- OrdersRepository.lookup(): LEFT JOINs customers and ORs ILIKE matchers\n  across order_number, customer email, first+last name, the walk-in label\n  (metadata->>'custom\n[…]\nh-insensitive), by\npartial order number; <3 chars returns a hint. Full core suite green\n(74 files / 433 passed); type-check clean.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(core): fuzzy order lookup GET /api/orders/lookup (#4)",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-06-14T16:46:18Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5be7f4274c6eb2523f1601e860da4f8b7183a24a",
          "body": "The endpoint returned a flat order array; every customer-profile UI then\nre-fetched all rows to compute lifetime spend. Add an opt-in server-side\nrollup.\n\n- ?include=totals wraps the response as { data: { items, totals } } with\n  totals = { count, lifetimeSpend, averageBasket }. lifetimeSpend exclud\n[…]\n, averageBasket:5000 } with a\nrefunded order excluded from spend. Full core suite green (73 files /\n429 passed); type-check clean.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(core): GET /api/customers/:id/orders ?include=totals rollup (#2)",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-06-14T16:41:55Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "1c7ade287e2cdbd05c501ed1b95efd45c9bad5bc",
          "body": "… (#7)\n\nPOST /api/inventory/adjust only took a signed adjustment and returned an\nopaque level. Add ergonomic modes and a confirmable result.\n\n- Body gains optional mode (add|remove|set) on an unsigned amount; mode\n  omitted ⇒ legacy signed adjustment (unchanged). remove clamps at 0; set\n  writes the\n[…]\ny adjustment still works. Existing inventory suite\ngreen (12/12); full core suite green (72 files / 427 passed); type-check\nclean.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(core): inventory adjust mode=add|remove|set + before/after/delta…",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-06-14T16:38:52Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c6c3f981e738574b58555b28ed2582aa998f78f7",
          "body": "PATCH replaced the whole metadata jsonb, so a single-key edit required a\nread-modify-write round-trip and could lose concurrent updates.\n\n- CustomerService.update() now shallow-merges top-level metadata keys with\n  the existing blob by default; pass { replaceMetadata: true } to overwrite.\n- Route ho\n[…]\nover { a,b } yields { a,b',c }; ?metadataReplace=true\noverwrites. Full core suite green (71 files / 423 passed); type-check clean.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(core): PATCH /api/customers/:id shallow-merges metadata (#8)",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-06-14T16:32:13Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "aad8d26419d565f404146f9466ff003f7ddd2608",
          "body": "Promotions supported create/validate/deactivate but no general edit, so\nevery integration wrote raw SQL that bypassed the create-time validation.\n\n- PromotionService.update(orgId, id, input): edits any subset of the\n  create body, re-running the same validation (value >= 0, type enum,\n  code uniquen\n[…]\nions:manage (403). Existing promotions\nsuite still green (15/15); full core suite green (70 files / 421 passed);\ntype-check clean.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(core): PATCH /api/promotions/:id to edit promotions (#6)",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-06-14T16:27:07Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ff2938d6f2a105667657f2898b355622dde5cc1a",
          "body": "createKernel() hard-required storage and threw at boot when config.storage\nwas unset, forcing every catalog-only consumer (and every Workers deploy,\nwhich has no shipped storage adapter) to hand-roll a stub just to start.\n\n- Add noopStorageAdapter (providerId 'noop'): getUrl passes the key\n  through\n[…]\nract (getUrl passthrough, upload unsupported);\nupload route returns 501 under noop. Full core suite green (69 files /\n417 passed).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(core): default to a no-op StorageAdapter when none configured (#27)",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-06-14T16:21:07Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "685613b3a31f300555fc04aa022cfeb0c33a9e48",
          "body": "server.ts hardcoded a global 1MB bodyLimit on \"*\", which blocked\nPOST /api/media/upload (phone photos are 3-8MB) before the request ever\nreached the route.\n\n- /api/media/upload gets its own bodyLimit (config.media.maxUploadSize,\n  default 10MB) returning 413 FILE_TOO_LARGE on overflow.\n- The global \n[…]\nILE_TOO_LARGE; a 2MB POST to a non-media route still returns\n413 PAYLOAD_TOO_LARGE. Full core suite green (68 files / 414 passed).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(core): exempt media upload from global 1MB body limit (#21)",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-06-14T16:16:37Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "1d7b90489672425fbc0ee66d1d833e8dc49b9050",
          "body": "Audit-row writes were scattered across handlers and easy to forget on new\nroutes. Add a Hono middleware that writes exactly one commerce_audit_log\nrow per successful (2xx) state-changing request.\n\n- auditMiddleware(kernel) exported from @porulle/core; one-line opt-in:\n  app.use('*', auditMiddleware(\n[…]\nrites nothing; non-2xx writes nothing;\nhandler overrides honored. Full core suite green (67 files / 411 passed);\ntype-check clean.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(core): auditMiddleware() — audit-by-default on 2xx mutations (#16)",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-06-14T16:12:58Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "3314ee949a25da97e902c058744ce874b89a060b",
          "body": "…ers (#17)\n\nReplace the unsafe (await c.req.json()) as T pattern with a validated,\nfield-mappable pipeline.\n\ncore:\n- parseJson<S>(c, schema): returns z.infer<S> or a 422 Response carrying\n  { error: { code: VALIDATION_FAILED, message, details: { issues[] } } };\n  malformed JSON returns 422 (not 500)\n[…]\nnvelope) and\nsdk errors (guard / flatten / no-issues). Full core suite green\n(66 files / 407 passed); core + sdk type-check clean.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(core,sdk): parseJson() + details.issues[] envelope + client mapp…",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-06-14T16:08:22Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8760cd0673935843f366918b3ab104ae37e370cb",
          "body": "…(#1)\n\nWhen auth.apiKeyScopes defines named scopes and none is 'default', every\nkey minted under a named scope failed the auth middleware with a silent\n401. The middleware called verifyApiKey without a configId; Better Auth's\napiKey plugin then (a) threw NO_DEFAULT_API_KEY_CONFIGURATION_FOUND in\nget\n[…]\n scope (no 'default' scope), and asserts it resolves to an api_key\nactor (was 401). Full core suite green (65 files / 403 passed).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(auth): forward configId in verifyApiKey so named-scope keys auth …",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-06-14T16:03:42Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7911c6c1068d85180165e2fb2727a00897df52dc",
          "body": "The promotion type enum was duplicated three ways (inline z.enum in the\nbody schema, a hand-written union in service.ts, and a literal validTypes\narray) and exported from none of the public surfaces, so consumers\nguessed values and got 400s.\n\n- Extract promotionTypeEnum in promotions/schemas.ts as t\n[…]\n to avoid pulling the kernel into frontend bundles —\nthe issue allows 'or equivalent'; the OpenAPI enum feeds SDK-generated\ntypes.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(core): export PromotionType union + single-source the enum (#23)",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-06-14T15:57:08Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "804bc26650c0354f06cc346a7d338f0d9b7cbde8",
          "body": "The 'create your first product' SDK snippet posted to /api/admin/entities\nwith a {name, fields, variants[]} body — neither the route nor that body\nshape exists in the shipped server. Rewrite against the verified surface:\n\n- POST /api/catalog/entities with {type, slug, basePrice, currency,\n  attribut\n[…]\nck\n- POST /api/catalog/entities/{id}/publish to publish\n- note that variants are created via the option/variant routes, not inline\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(readme): fix quick-start to real /api/catalog surface (#29)",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-06-14T15:53:59Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ca728ff14a9b4f13e0446202ed57fe2ba2f1c75e",
          "body": "mediaAssets, entityMedia and auditLog (commerce_audit_log) are already\nre-exported from @porulle/core/schema in current source (the gap reported\nagainst 0.1.0 was fixed before this commit). Add a regression test so the\npublic schema surface can't silently drop these tables again.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "test(core): pin media + audit schema re-exports from /schema (#20)",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-06-14T15:50:47Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "a1f24040a7ea48e850f4f0d0870527b88707f76b",
          "body": "The migrate module's docstring promised npm consumers getSchemaFiles()\nand pushSchema(), but neither was implemented or exported — the public\nentry only re-exported getSchema/buildSchema/getTableNames, so the\ndocumented drizzle.config.ts recipe couldn't be written and there was no\nprogrammatic schem\n[…]\nontract test imports both from the package entry and verifies\n  pushSchema() actually creates sellable_entities in a fresh PGlite.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(core): implement & export getSchemaFiles() and pushSchema() (#26)",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-06-14T15:49:54Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "13505dd8d1faf66bedfb5893e0e62a0e4c14e686",
          "body": "@porulle/cli declared @porulle/import-{flat,shopify,woocommerce} as\nworkspace:* dependencies. workspace:* must never appear in a published\nmanifest, so any registry install of the CLI failed to resolve — which\naborted the whole install, breaking the documented 'bunx @porulle/cli\ninit' path.\n\n- Move \n[…]\nots even when an adapter isn't installed; a missing adapter\n  yields a clear 'bun add <pkg>' message instead of a load-time crash.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(cli): lazy-load import adapters; move to optionalDependencies (#24)",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-06-14T15:47:32Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4a634ca779aaa60376a14d71d4e465c18565cc38",
          "body": "@porulle/core imports @better-auth/api-key in auth/setup.ts but only\ndeclared it in devDependencies, so clean/isolated installs (bun default,\npnpm without hoisting, Yarn PnP) threw 'Cannot find module\n@better-auth/api-key' at createServer(). Move it to dependencies,\nversion-aligned with the better-auth ^1.3.8 range.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(core): declare @better-auth/api-key as a runtime dependency (#25)",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-06-14T15:43:55Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "df8788277123ba6578831c100a7ee82a9f1a1f3c",
          "body": "Headless commerce framework for TypeScript. REST-only, security-hardened\n(post-VAPT), self-host-first. 32 packages published to @porulle/* on npm\n— core kernel, adapters (Postgres / Stripe / S3 / R2 / Resend / SES /\nMeilisearch / TaxJar / Tax-Manual), plugins (POS, gift cards, supply\nchain, marketpl\n[…]\nttps://porulle-docs.vercel.app\nnpm:  https://www.npmjs.com/org/porulle\n\nActive development. Alpha-grade. Straight out of the oven.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Initial commit — Porulle v0.1.0 alpha",
          "author_name": "octalpixel",
          "author_login": "octalpixel",
          "committed_at": "2026-05-11T21:13:06Z",
          "body_truncated": true,
          "is_coding_agent": true
        }
      ],
      "releases_count": 2,
      "commits_last_year": 96,
      "latest_release_at": "2026-06-14T19:10:29Z",
      "latest_release_tag": "v0.6.0",
      "releases_from_tags": false,
      "days_since_last_push": 5,
      "active_weeks_last_year": 5,
      "days_since_latest_release": 39,
      "mean_days_between_releases": 0
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": false,
      "health_percentage": 62,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": [
        {
          "name": "@porulle/db",
          "exists": true,
          "license": "MIT",
          "keywords": [],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/@porulle/db",
          "is_deprecated": false,
          "latest_version": "0.10.4",
          "repository_url": "https://github.com/asyncdotengineering/porulle",
          "versions_count": 11,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 1,
          "monthly_downloads": 1409,
          "first_published_at": "2026-05-10T20:48:09.900000Z",
          "latest_published_at": "2026-07-18T18:05:36.560000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 5
        },
        {
          "name": "@porulle/cli",
          "exists": true,
          "license": "MIT",
          "keywords": [],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/@porulle/cli",
          "is_deprecated": false,
          "latest_version": "0.10.4",
          "repository_url": "https://github.com/asyncdotengineering/porulle",
          "versions_count": 11,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 1,
          "monthly_downloads": 1248,
          "first_published_at": "2026-05-10T20:48:09.673000Z",
          "latest_published_at": "2026-07-18T18:05:36.383000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 5
        },
        {
          "name": "@porulle/sdk",
          "exists": true,
          "license": "MIT",
          "keywords": [],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/@porulle/sdk",
          "is_deprecated": false,
          "latest_version": "0.10.4",
          "repository_url": "https://github.com/asyncdotengineering/porulle",
          "versions_count": 11,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 1,
          "monthly_downloads": 1182,
          "first_published_at": "2026-05-10T20:48:19.033000Z",
          "latest_published_at": "2026-07-18T18:05:43.070000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 5
        },
        {
          "name": "@porulle/core",
          "exists": true,
          "license": "MIT",
          "keywords": [],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/@porulle/core",
          "is_deprecated": false,
          "latest_version": "0.10.4",
          "repository_url": "https://github.com/asyncdotengineering/porulle",
          "versions_count": 11,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 1,
          "monthly_downloads": 4194,
          "first_published_at": "2026-05-10T20:48:11.640000Z",
          "latest_published_at": "2026-07-18T18:05:38.664000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 5
        },
        {
          "name": "@porulle/jobs-inngest",
          "exists": true,
          "license": "MIT",
          "keywords": [],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/@porulle/jobs-inngest",
          "is_deprecated": false,
          "latest_version": "0.10.4",
          "repository_url": "https://github.com/asyncdotengineering/porulle",
          "versions_count": 6,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 1,
          "monthly_downloads": 778,
          "first_published_at": "2026-07-18T10:51:34.322000Z",
          "latest_published_at": "2026-07-18T18:05:38.336000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 5
        },
        {
          "name": "@porulle/jobs-pg-boss",
          "exists": true,
          "license": "MIT",
          "keywords": [],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/@porulle/jobs-pg-boss",
          "is_deprecated": false,
          "latest_version": "0.10.4",
          "repository_url": "https://github.com/asyncdotengineering/porulle",
          "versions_count": 6,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 1,
          "monthly_downloads": 766,
          "first_published_at": "2026-07-18T10:51:34.312000Z",
          "latest_published_at": "2026-07-18T18:05:38.457000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 5
        },
        {
          "name": "@porulle/jobs-trigger",
          "exists": true,
          "license": "MIT",
          "keywords": [],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/@porulle/jobs-trigger",
          "is_deprecated": false,
          "latest_version": "0.10.4",
          "repository_url": "https://github.com/asyncdotengineering/porulle",
          "versions_count": 6,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 1,
          "monthly_downloads": 738,
          "first_published_at": "2026-07-18T10:51:34.969000Z",
          "latest_published_at": "2026-07-18T18:05:39.447000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 5
        },
        {
          "name": "@porulle/jobs-cloudflare",
          "exists": true,
          "license": "MIT",
          "keywords": [],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/@porulle/jobs-cloudflare",
          "is_deprecated": false,
          "latest_version": "0.10.4",
          "repository_url": "https://github.com/asyncdotengineering/porulle",
          "versions_count": 6,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 1,
          "monthly_downloads": 763,
          "first_published_at": "2026-07-18T10:51:35.182000Z",
          "latest_published_at": "2026-07-18T18:05:38.363000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 5
        }
      ]
    },
    "popularity": {
      "forks": 0,
      "stars": 0,
      "watchers": 0,
      "fork_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_forks": 0
      },
      "star_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_stars": 0,
        "collected_at": null
      },
      "open_issues_and_prs": 0
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [],
      "has_llms_txt": false,
      "has_dockerfile": true,
      "has_mcp_signal": true,
      "bootstrap_files": [],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [
        "apps/docs/public/scaffold/tsconfig.json",
        "apps/docs/tsconfig.json",
        "apps/restaurant-example/tsconfig.json",
        "apps/saas-example/tsconfig.json",
        "apps/store-example/tsconfig.json",
        "apps/tea-avenue/tsconfig.json",
        "apps/web/tsconfig.json",
        "packages/adapters/adapter-local-storage/tsconfig.json",
        "packages/adapters/adapter-meilisearch/tsconfig.json",
        "packages/adapters/adapter-neon/tsconfig.json",
        "packages/adapters/adapter-pg-search/tsconfig.json",
        "packages/adapters/adapter-pglite/tsconfig.json",
        "packages/adapters/adapter-postgres/tsconfig.json",
        "packages/adapters/adapter-r2/tsconfig.json",
        "packages/adapters/adapter-resend/tsconfig.json",
        "packages/adapters/adapter-s3/tsconfig.json",
        "packages/adapters/adapter-ses/tsconfig.json",
        "packages/adapters/adapter-shopify/tsconfig.json",
        "packages/adapters/adapter-stripe/tsconfig.json",
        "packages/adapters/adapter-tax-manual/tsconfig.json",
        "packages/adapters/adapter-taxjar/tsconfig.json",
        "packages/adapters/adapter-woocommerce/tsconfig.json",
        "packages/cli/templates/starter/tsconfig.json",
        "packages/cli/tsconfig.json",
        "packages/core/tsconfig.json",
        "packages/db/tsconfig.json",
        "packages/import/import-flat/tsconfig.json",
        "packages/import/import-shopify/tsconfig.json",
        "packages/import/import-woocommerce/tsconfig.json",
        "packages/jobs-cloudflare/tsconfig.json",
        "packages/jobs-inngest/tsconfig.json",
        "packages/jobs-pg-boss/tsconfig.json",
        "packages/jobs-trigger/tsconfig.json",
        "packages/plugins/plugin-appointments/tsconfig.json",
        "packages/plugins/plugin-channel-connector/tsconfig.json",
        "packages/plugins/plugin-gift-cards/tsconfig.json",
        "packages/plugins/plugin-layaway/tsconfig.json",
        "packages/plugins/plugin-loyalty/tsconfig.json",
        "packages/plugins/plugin-marketplace/tsconfig.json",
        "packages/plugins/plugin-notifications/tsconfig.json",
        "packages/plugins/plugin-pos-restaurant/tsconfig.json",
        "packages/plugins/plugin-pos/tsconfig.json",
        "packages/plugins/plugin-procurement/tsconfig.json",
        "packages/plugins/plugin-production/tsconfig.json",
        "packages/plugins/plugin-reviews/tsconfig.json",
        "packages/plugins/plugin-scheduled-orders/tsconfig.json",
        "packages/plugins/plugin-uom/tsconfig.json",
        "packages/plugins/plugin-warehouse/tsconfig.json",
        "packages/plugins/plugin-wishlist/tsconfig.json",
        "packages/sdk/tsconfig.json"
      ],
      "toolchain_manifests": [],
      "largest_source_bytes": 59740,
      "source_files_sampled": 804,
      "oversized_source_files": 0,
      "agent_instruction_files": [
        ".agents/factory/workers/claude.md",
        ".archive/research/AGENTS.md",
        "CLAUDE.md"
      ],
      "agent_instruction_max_bytes": 13046
    },
    "dependencies": {
      "manifests": [
        "package.json"
      ],
      "advisories": {
        "error": null,
        "scope": "published_package",
        "source": "osv",
        "findings": [],
        "collected": true,
        "malicious": [],
        "truncated": false,
        "by_severity": {},
        "advisory_count": 0,
        "affected_count": 0,
        "assessed_count": 57,
        "malicious_count": 0,
        "assessed_package": "npm:@porulle/db@0.10.4",
        "unassessed_count": 0,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "npm"
      ],
      "dependencies": [
        {
          "name": "@hono/node-server",
          "manifest": "apps/restaurant-example/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.14.3"
        },
        {
          "name": "@porulle/adapter-local-storage",
          "manifest": "apps/restaurant-example/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@porulle/adapter-postgres",
          "manifest": "apps/restaurant-example/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@porulle/core",
          "manifest": "apps/restaurant-example/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@porulle/plugin-pos",
          "manifest": "apps/restaurant-example/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@porulle/plugin-pos-restaurant",
          "manifest": "apps/restaurant-example/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@porulle/plugin-uom",
          "manifest": "apps/restaurant-example/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@porulle/plugin-procurement",
          "manifest": "apps/restaurant-example/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@porulle/plugin-warehouse",
          "manifest": "apps/restaurant-example/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@porulle/plugin-production",
          "manifest": "apps/restaurant-example/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@porulle/plugin-notifications",
          "manifest": "apps/restaurant-example/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@porulle/plugin-scheduled-orders",
          "manifest": "apps/restaurant-example/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@porulle/plugin-reviews",
          "manifest": "apps/restaurant-example/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "hono",
          "manifest": "apps/restaurant-example/package.json",
          "ecosystem": "npm",
          "version_constraint": "^4.12.5"
        },
        {
          "name": "@hono/node-server",
          "manifest": "apps/saas-example/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.19.6"
        },
        {
          "name": "@porulle/adapter-local-storage",
          "manifest": "apps/saas-example/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@porulle/adapter-postgres",
          "manifest": "apps/saas-example/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@porulle/core",
          "manifest": "apps/saas-example/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@faker-js/faker",
          "manifest": "apps/store-example/package.json",
          "ecosystem": "npm",
          "version_constraint": "^10.3.0"
        },
        {
          "name": "@hono/node-server",
          "manifest": "apps/store-example/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.19.6"
        },
        {
          "name": "@hono/zod-openapi",
          "manifest": "apps/store-example/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.2.2"
        },
        {
          "name": "hono",
          "manifest": "apps/store-example/package.json",
          "ecosystem": "npm",
          "version_constraint": "^4.9.8"
        },
        {
          "name": "@porulle/adapter-local-storage",
          "manifest": "apps/store-example/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@porulle/adapter-postgres",
          "manifest": "apps/store-example/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@porulle/core",
          "manifest": "apps/store-example/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@porulle/plugin-loyalty",
          "manifest": "apps/store-example/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@porulle/plugin-wishlist",
          "manifest": "apps/store-example/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@porulle/plugin-reviews",
          "manifest": "apps/store-example/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@hono/node-server",
          "manifest": "apps/tea-avenue/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.14.3"
        },
        {
          "name": "@porulle/adapter-local-storage",
          "manifest": "apps/tea-avenue/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@porulle/adapter-postgres",
          "manifest": "apps/tea-avenue/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@porulle/core",
          "manifest": "apps/tea-avenue/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@porulle/plugin-pos",
          "manifest": "apps/tea-avenue/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@porulle/plugin-pos-restaurant",
          "manifest": "apps/tea-avenue/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@porulle/plugin-uom",
          "manifest": "apps/tea-avenue/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@porulle/plugin-procurement",
          "manifest": "apps/tea-avenue/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@porulle/plugin-warehouse",
          "manifest": "apps/tea-avenue/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@porulle/plugin-production",
          "manifest": "apps/tea-avenue/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@porulle/plugin-loyalty",
          "manifest": "apps/tea-avenue/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@porulle/plugin-notifications",
          "manifest": "apps/tea-avenue/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@porulle/plugin-scheduled-orders",
          "manifest": "apps/tea-avenue/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@porulle/plugin-reviews",
          "manifest": "apps/tea-avenue/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@porulle/plugin-wishlist",
          "manifest": "apps/tea-avenue/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "hono",
          "manifest": "apps/tea-avenue/package.json",
          "ecosystem": "npm",
          "version_constraint": "^4.12.5"
        },
        {
          "name": "next",
          "manifest": "apps/web/package.json",
          "ecosystem": "npm",
          "version_constraint": "16.1.5"
        },
        {
          "name": "react",
          "manifest": "apps/web/package.json",
          "ecosystem": "npm",
          "version_constraint": "^19.2.0"
        },
        {
          "name": "react-dom",
          "manifest": "apps/web/package.json",
          "ecosystem": "npm",
          "version_constraint": "^19.2.0"
        },
        {
          "name": "postgres",
          "manifest": "packages/cli/package.json",
          "ecosystem": "npm",
          "version_constraint": "^3.4.7"
        },
        {
          "name": "citty",
          "manifest": "packages/cli/package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.1.6"
        },
        {
          "name": "consola",
          "manifest": "packages/cli/package.json",
          "ecosystem": "npm",
          "version_constraint": "^3.4.2"
        },
        {
          "name": "giget",
          "manifest": "packages/cli/package.json",
          "ecosystem": "npm",
          "version_constraint": "^2.0.0"
        },
        {
          "name": "@better-auth/api-key",
          "manifest": "packages/core/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.3.8"
        },
        {
          "name": "@better-auth/drizzle-adapter",
          "manifest": "packages/core/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.3.8"
        },
        {
          "name": "@hono/zod-openapi",
          "manifest": "packages/core/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.2.2"
        },
        {
          "name": "@scalar/hono-api-reference",
          "manifest": "packages/core/package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.10.5"
        },
        {
          "name": "better-auth",
          "manifest": "packages/core/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.3.8"
        },
        {
          "name": "drizzle-orm",
          "manifest": "packages/core/package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.45.1"
        },
        {
          "name": "drizzle-zod",
          "manifest": "packages/core/package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.8.3"
        },
        {
          "name": "hono",
          "manifest": "packages/core/package.json",
          "ecosystem": "npm",
          "version_constraint": "^4.9.8"
        },
        {
          "name": "hono-rate-limiter",
          "manifest": "packages/core/package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.5.3"
        },
        {
          "name": "pino",
          "manifest": "packages/core/package.json",
          "ecosystem": "npm",
          "version_constraint": "^10.3.1"
        },
        {
          "name": "zod",
          "manifest": "packages/core/package.json",
          "ecosystem": "npm",
          "version_constraint": "^4.1.11"
        },
        {
          "name": "@porulle/core",
          "manifest": "packages/db/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "drizzle-orm",
          "manifest": "packages/db/package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.45.1"
        },
        {
          "name": "postgres",
          "manifest": "packages/db/package.json",
          "ecosystem": "npm",
          "version_constraint": "^3.4.7"
        },
        {
          "name": "@porulle/core",
          "manifest": "packages/jobs-cloudflare/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@porulle/core",
          "manifest": "packages/jobs-inngest/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "inngest",
          "manifest": "packages/jobs-inngest/package.json",
          "ecosystem": "npm",
          "version_constraint": "^4.13.0"
        },
        {
          "name": "@porulle/core",
          "manifest": "packages/jobs-pg-boss/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "pg-boss",
          "manifest": "packages/jobs-pg-boss/package.json",
          "ecosystem": "npm",
          "version_constraint": "^12.26.1"
        },
        {
          "name": "@porulle/core",
          "manifest": "packages/jobs-trigger/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@trigger.dev/sdk",
          "manifest": "packages/jobs-trigger/package.json",
          "ecosystem": "npm",
          "version_constraint": "^4.5.4"
        },
        {
          "name": "openapi-fetch",
          "manifest": "packages/sdk/package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.17.0"
        },
        {
          "name": "openapi-typescript-helpers",
          "manifest": "packages/sdk/package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.1.0"
        }
      ],
      "all_dependencies": {
        "error": "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
        "source": null,
        "packages": [],
        "collected": false,
        "truncated": false,
        "total_count": null,
        "direct_count": null,
        "indirect_count": null
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 0,
        "merged_prs": 13,
        "open_issues": 0,
        "closed_ratio": 1,
        "closed_issues": 55,
        "closed_unmerged_prs": 0
      },
      "bus_factor": 1,
      "bot_contributors": 0,
      "top_contributors": [
        {
          "type": "User",
          "login": "octalpixel",
          "commits": 96,
          "avatar_url": "https://avatars.githubusercontent.com/u/30002284?v=4"
        }
      ],
      "contributors_sampled": 1,
      "top_contributor_share": 1
    },
    "quality_signals": {
      "has_ci": false,
      "has_tests": true,
      "ci_workflows": [],
      "has_docs_dir": true,
      "linter_configs": [
        "eslint.config.js",
        "eslint.config.mjs"
      ],
      "has_editorconfig": false,
      "has_linter_config": true,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [
        "pnpm-lock.yaml"
      ],
      "scorecard": {
        "checks": [
          {
            "name": "Binary-Artifacts",
            "score": 10,
            "reason": "no binaries found in the repo",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
          },
          {
            "name": "Branch-Protection",
            "score": 0,
            "reason": "branch protection not enabled on development/release branches",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": 0,
            "reason": "0 out of 9 merged PRs checked by a CI test -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
          },
          {
            "name": "CII-Best-Practices",
            "score": 0,
            "reason": "no effort to earn an OpenSSF best practices badge detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
          },
          {
            "name": "Code-Review",
            "score": 0,
            "reason": "Found 0/13 approved changesets -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 3,
            "reason": "project has 1 contributing companies or organizations -- score normalized to 3",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": null,
            "reason": "no workflows found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
          },
          {
            "name": "Dependency-Update-Tool",
            "score": 0,
            "reason": "no update tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
          },
          {
            "name": "Fuzzing",
            "score": 0,
            "reason": "project is not fuzzed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
          },
          {
            "name": "License",
            "score": 10,
            "reason": "license file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 0,
            "reason": "project was created within the last 90 days. Please review its contents carefully",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
          },
          {
            "name": "Packaging",
            "score": null,
            "reason": "packaging workflow not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": 0,
            "reason": "dependency not pinned by hash detected -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "SAST tool is not run on all commits -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 10,
            "reason": "security policy file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": null,
            "reason": "no releases found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": null,
            "reason": "No tokens found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 0,
            "reason": "54 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "017b18c2077d3e5401116ba6245b5b2d6183457e",
        "ran_at": "2026-07-24T03:58:43Z",
        "aggregate_score": 2.1,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": true,
      "has_dependabot_config": false
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": null,
      "oldest_open_prs": [],
      "last_merged_pr_at": "2026-07-18T18:03:02Z",
      "ci_last_conclusion": null,
      "oldest_open_issues": []
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/asyncdotengineering/porulle",
    "host": "github.com",
    "name": "porulle",
    "owner": "asyncdotengineering"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 54,
      "inputs": {
        "security": 37,
        "vitality": 74,
        "community": 35,
        "governance": 56,
        "engineering": 60
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "good",
        "name": "Vitality",
        "value": 74,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "moderate",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 57,
            "inputs": {
              "commits_last_year": 96,
              "human_commit_share": 1,
              "days_since_last_push": 5,
              "active_weeks_last_year": 5
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 5 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 5
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "5/52 weeks with commits",
                "points": 3.5,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 5
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "96 commits in the last year",
                "points": 17.8,
                "status": "partial",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 96
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "project was created within the last 90 days. Please review its contents carefully",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "excellent",
            "name": "Release discipline",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "releases_count": 2,
              "latest_release_tag": "v0.6.0",
              "releases_from_tags": false,
              "days_since_latest_release": 39,
              "mean_days_between_releases": 0
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "2 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 39 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 39
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~0 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 0
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "openssf_scorecard_signed_releases",
                "name": "OpenSSF Scorecard: Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              }
            ]
          },
          {
            "key": "abandonment",
            "band": "excellent",
            "name": "Abandonment",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "cap": null,
              "state": "unverified",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": "repository_too_young",
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": null,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "maintenance record not established from the collected data",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_unverified",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "at_risk",
        "name": "Community & Adoption",
        "value": 35,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 1,
            "inputs": {
              "forks": 0,
              "stars": 0,
              "watchers": 0,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "0 stars",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "0 forks",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "0 watchers",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "moderate",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 50,
            "inputs": {
              "has_readme": true,
              "has_license": true,
              "has_contributing": false,
              "has_issue_template": false,
              "has_code_of_conduct": false,
              "has_pull_request_template": false
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 22.5,
                "status": "met",
                "details": [],
                "max_points": 22.5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "recognized license (MIT)",
                "points": 22.5,
                "status": "met",
                "details": [
                  {
                    "code": "license_standard",
                    "params": {}
                  },
                  {
                    "code": "license_spdx",
                    "params": {
                      "spdx": "MIT"
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributing_guide",
                "name": "CONTRIBUTING guide",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 18
              },
              {
                "key": "code_of_conduct",
                "name": "Code of conduct",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 13.5
              },
              {
                "key": "issue_template",
                "name": "Issue template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.2
              },
              {
                "key": "pr_template",
                "name": "PR template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.3
              }
            ]
          },
          {
            "key": "ecosystem_adoption",
            "band": "moderate",
            "name": "Ecosystem adoption (downloads)",
            "note": "Excluded from scoring (no data or not applicable): Registry dependents. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "registry_dependents"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 67,
            "inputs": {
              "packages": [
                "@porulle/db",
                "@porulle/cli",
                "@porulle/sdk",
                "@porulle/core",
                "@porulle/jobs-inngest",
                "@porulle/jobs-pg-boss",
                "@porulle/jobs-trigger",
                "@porulle/jobs-cloudflare"
              ],
              "dependents": null,
              "ecosystems": "npm",
              "total_downloads": null,
              "monthly_downloads": 11078
            },
            "components": [
              {
                "key": "monthly_downloads",
                "name": "Monthly downloads",
                "detail": "11,078 downloads/month across npm",
                "points": 53.9,
                "status": "partial",
                "details": [
                  {
                    "code": "downloads_monthly",
                    "params": {
                      "count": 11078,
                      "ecosystems": "npm"
                    }
                  }
                ],
                "max_points": 80
              },
              {
                "key": "registry_dependents",
                "name": "Registry dependents",
                "detail": "not reported by this ecosystem",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "not_reported_by_this_ecosystem",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "moderate",
        "name": "Sustainability & Governance",
        "value": 56,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "critical",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 13,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 1,
              "top_contributor_share": 1
            },
            "components": [
              {
                "key": "bus_factor",
                "name": "Bus factor",
                "detail": "1 contributor(s) cover half of all commits",
                "points": 9,
                "status": "partial",
                "details": [
                  {
                    "code": "bus_factor",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 54
              },
              {
                "key": "commit_distribution",
                "name": "Commit distribution",
                "detail": "top contributor authored 100% of commits",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 100
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "1 contributors",
                "points": 1.4,
                "status": "partial",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 1 contributing companies or organizations -- score normalized to 3",
                "points": 3,
                "status": "partial",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "excellent",
            "name": "Issue & PR responsiveness",
            "note": null,
            "notes": [],
            "value": 85,
            "inputs": {
              "merged_prs": 13,
              "open_issues": 0,
              "closed_issues": 55,
              "issue_closed_ratio": 1,
              "closed_unmerged_prs": 0
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "100% of issues closed",
                "points": 46.8,
                "status": "met",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 100
                    }
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "13/13 decided PRs merged",
                "points": 38.2,
                "status": "met",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 13,
                      "decided": 13
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 0/13 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "at_risk",
            "name": "Ownership & stewardship",
            "note": null,
            "notes": [],
            "value": 44,
            "inputs": {
              "followers": 0,
              "owner_type": "Organization",
              "is_verified": null,
              "owner_login": "asyncdotengineering",
              "public_repos": 9,
              "account_age_days": 1197
            },
            "components": [
              {
                "key": "ownership_backing",
                "name": "Ownership backing",
                "detail": "organization-owned",
                "points": 30,
                "status": "met",
                "details": [
                  {
                    "code": "owner_organization",
                    "params": {}
                  }
                ],
                "max_points": 30
              },
              {
                "key": "verified_domain",
                "name": "Verified domain",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              },
              {
                "key": "owner_reach",
                "name": "Owner reach",
                "detail": "0 followers of asyncdotengineering",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 0,
                      "login": "asyncdotengineering"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "9 public repos, account ~3 yr old",
                "points": 13.8,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 9
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 3
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "@porulle/db",
                "@porulle/cli",
                "@porulle/sdk",
                "@porulle/core",
                "@porulle/jobs-inngest",
                "@porulle/jobs-pg-boss",
                "@porulle/jobs-trigger",
                "@porulle/jobs-cloudflare"
              ],
              "ecosystems": "npm",
              "any_deprecated": false,
              "min_days_since_publish": 5
            },
            "components": [
              {
                "key": "published_resolvable",
                "name": "Published & resolvable",
                "detail": "8 package(s) on npm",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "packages_published",
                    "params": {
                      "count": 8,
                      "ecosystems": "npm"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "publish_recency",
                "name": "Publish recency",
                "detail": "latest publish 5 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 5
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "11 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 11
                    }
                  }
                ],
                "max_points": 20
              },
              {
                "key": "not_deprecated",
                "name": "Not deprecated",
                "detail": "active, not deprecated or yanked",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "package_not_deprecated",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
      },
      {
        "key": "engineering",
        "band": "moderate",
        "name": "Engineering Quality",
        "value": 60,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "at_risk",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "has_ci": false,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": true,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 24
              },
              {
                "key": "tests_present",
                "name": "Tests present",
                "detail": null,
                "points": 24,
                "status": "met",
                "details": [],
                "max_points": 24
              },
              {
                "key": "linter_config",
                "name": "Linter config",
                "detail": "eslint.config.js, eslint.config.mjs",
                "points": 16,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "eslint.config.js, eslint.config.mjs"
                    }
                  }
                ],
                "max_points": 16
              },
              {
                "key": "pre_commit_hooks",
                "name": "Pre-commit hooks",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 9.6
              },
              {
                "key": "editorconfig",
                "name": ".editorconfig",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.4
              },
              {
                "key": "openssf_scorecard_ci_tests",
                "name": "OpenSSF Scorecard: CI-Tests",
                "detail": "0 out of 9 merged PRs checked by a CI test -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "excellent",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 90,
            "inputs": {
              "topics": [],
              "has_wiki": true,
              "homepage": "https://porulle-docs.vercel.app",
              "has_readme": true,
              "has_docs_dir": true,
              "has_description": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 30,
                "status": "met",
                "details": [],
                "max_points": 30
              },
              {
                "key": "documentation_directory",
                "name": "Documentation directory",
                "detail": null,
                "points": 25,
                "status": "met",
                "details": [],
                "max_points": 25
              },
              {
                "key": "documentation_homepage_site",
                "name": "Documentation / homepage site",
                "detail": "https://porulle-docs.vercel.app",
                "points": 15,
                "status": "met",
                "details": [],
                "max_points": 15
              },
              {
                "key": "repository_description",
                "name": "Repository description",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "topics",
                "name": "Topics",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              },
              {
                "key": "wiki",
                "name": "Wiki",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "at_risk",
        "name": "Security",
        "value": 37,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "critical",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): Dangerous-Workflow, Packaging, Signed-Releases, Token-Permissions. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "dangerous_workflow",
                    "packaging",
                    "signed_releases",
                    "token_permissions"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 21,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 14,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 4,
              "scorecard_aggregate": 2.1
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "no binaries found in the repo",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "branch_protection",
                "name": "Branch-Protection",
                "detail": "branch protection not enabled on development/release branches",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "0 out of 9 merged PRs checked by a CI test -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "cii_best_practices",
                "name": "CII-Best-Practices",
                "detail": "no effort to earn an OpenSSF best practices badge detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "code_review",
                "name": "Code-Review",
                "detail": "Found 0/13 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 1 contributing companies or organizations -- score normalized to 3",
                "points": 0.8,
                "status": "partial",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no workflows found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              },
              {
                "key": "dependency_update_tool",
                "name": "Dependency-Update-Tool",
                "detail": "no update tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "fuzzing",
                "name": "Fuzzing",
                "detail": "project is not fuzzed",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file detected",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "project was created within the last 90 days. Please review its contents carefully",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "packaging",
                "name": "Packaging",
                "detail": "packaging workflow not detected",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "SAST tool is not run on all commits -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file detected",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "No tokens found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "54 existing vulnerabilities detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "key": "dependency_advisories",
            "band": "excellent",
            "name": "Dependency advisories",
            "note": "Excluded from scoring (no data or not applicable): No advisories left outstanding. Remaining weights renormalized. Matched the npm:@porulle/db@0.10.4 runtime dependency closure — what installing the published package pulls in — 57 packages. Reachability is not analyzed.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "no_advisories_left_outstanding"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              },
              {
                "code": "advisories_scope_published",
                "params": {
                  "package": "npm:@porulle/db@0.10.4",
                  "assessed": 57
                }
              },
              {
                "code": "advisories_reachability",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "source": "osv",
              "advisories": 0,
              "affected_packages": 0,
              "assessed_packages": 57,
              "unassessed_packages": 0,
              "affected_by_severity": "none",
              "direct_affected_packages": 0
            },
            "components": [
              {
                "key": "direct_dependencies_free_of_known_advisories",
                "name": "Direct dependencies free of known advisories",
                "detail": "no direct dependency carries a known advisory",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "no_direct_advisories",
                    "params": {}
                  }
                ],
                "max_points": 35
              },
              {
                "key": "indirect_dependencies_free_of_known_advisories",
                "name": "Indirect dependencies free of known advisories",
                "detail": "no indirect dependency carries a known advisory",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "no_indirect_advisories",
                    "params": {}
                  }
                ],
                "max_points": 25
              },
              {
                "key": "no_advisories_left_outstanding",
                "name": "No advisories left outstanding",
                "detail": "no advisory carries a publication date",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "advisories_no_publication_date",
                    "params": {}
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "malicious_dependencies",
            "band": "excellent",
            "name": "Malicious dependencies",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "source": "osv",
              "meaning": "reported as a malicious package by the OpenSSF corpus; the remedy is removal or moving off the compromised name, never an upgrade of the same artifact. Versions the registry has since pulled are listed but not scored",
              "packages": [],
              "red_flag": false,
              "assessed_packages": 57,
              "malicious_packages": 0,
              "direct_malicious_packages": 0,
              "withdrawn_malicious_packages": 0,
              "installable_malicious_packages": 0
            },
            "components": [
              {
                "key": "no_dependency_reported_as_a_malicious_package",
                "name": "No dependency reported as a malicious package",
                "detail": "no dependency is reported as a malicious package",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "no_malicious_dependencies",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          },
          {
            "key": "high_risk_jurisdiction_exposure",
            "band": "excellent",
            "name": "High-Risk Jurisdiction Exposure",
            "note": "Only high-confidence self-published location evidence affects this multiplier. Ambiguous matches are review-only; country evidence is not proof of nationality, citizenship, legal registration, malicious intent, or sanctions status.",
            "notes": [
              {
                "code": "jurisdiction_evidence_limits",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "meaning": "self-published location evidence; not nationality or citizenship",
              "red_flag": false,
              "exposures": [],
              "policy_countries": [
                "Russia",
                "Iran",
                "North Korea"
              ],
              "review_only_matches": 0,
              "assessed_self_published_locations": 1
            },
            "components": [
              {
                "key": "policy_exposure_multiplier",
                "name": "Policy exposure multiplier",
                "detail": "no confirmed policy-scope location match",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "jurisdiction_no_match",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
      },
      {
        "key": "ai_readiness",
        "band": "moderate",
        "name": "AI Readiness",
        "value": 69,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "excellent",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 85,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 1,
              "agent_instruction_files": [
                ".agents/factory/workers/claude.md",
                ".archive/research/AGENTS.md",
                "CLAUDE.md"
              ],
              "agent_instruction_max_bytes": 13046
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": ".agents/factory/workers/claude.md, .archive/research/AGENTS.md, CLAUDE.md",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": ".agents/factory/workers/claude.md, .archive/research/AGENTS.md, CLAUDE.md"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "machine_readable_docs_llms_txt",
                "name": "Machine-readable docs (llms.txt)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "96 of 96 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 96,
                      "sampled": 96
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "moderate",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 64,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [
                "pnpm-lock.yaml"
              ],
              "has_dockerfile": true,
              "typed_language": true,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": true,
              "typecheck_configs": [
                "apps/docs/public/scaffold/tsconfig.json",
                "apps/docs/tsconfig.json",
                "apps/restaurant-example/tsconfig.json",
                "apps/saas-example/tsconfig.json",
                "apps/store-example/tsconfig.json",
                "apps/tea-avenue/tsconfig.json",
                "apps/web/tsconfig.json",
                "packages/adapters/adapter-local-storage/tsconfig.json",
                "packages/adapters/adapter-meilisearch/tsconfig.json",
                "packages/adapters/adapter-neon/tsconfig.json",
                "packages/adapters/adapter-pg-search/tsconfig.json",
                "packages/adapters/adapter-pglite/tsconfig.json",
                "packages/adapters/adapter-postgres/tsconfig.json",
                "packages/adapters/adapter-r2/tsconfig.json",
                "packages/adapters/adapter-resend/tsconfig.json",
                "packages/adapters/adapter-s3/tsconfig.json",
                "packages/adapters/adapter-ses/tsconfig.json",
                "packages/adapters/adapter-shopify/tsconfig.json",
                "packages/adapters/adapter-stripe/tsconfig.json",
                "packages/adapters/adapter-tax-manual/tsconfig.json",
                "packages/adapters/adapter-taxjar/tsconfig.json",
                "packages/adapters/adapter-woocommerce/tsconfig.json",
                "packages/cli/templates/starter/tsconfig.json",
                "packages/cli/tsconfig.json",
                "packages/core/tsconfig.json",
                "packages/db/tsconfig.json",
                "packages/import/import-flat/tsconfig.json",
                "packages/import/import-shopify/tsconfig.json",
                "packages/import/import-woocommerce/tsconfig.json",
                "packages/jobs-cloudflare/tsconfig.json",
                "packages/jobs-inngest/tsconfig.json",
                "packages/jobs-pg-boss/tsconfig.json",
                "packages/jobs-trigger/tsconfig.json",
                "packages/plugins/plugin-appointments/tsconfig.json",
                "packages/plugins/plugin-channel-connector/tsconfig.json",
                "packages/plugins/plugin-gift-cards/tsconfig.json",
                "packages/plugins/plugin-layaway/tsconfig.json",
                "packages/plugins/plugin-loyalty/tsconfig.json",
                "packages/plugins/plugin-marketplace/tsconfig.json",
                "packages/plugins/plugin-notifications/tsconfig.json",
                "packages/plugins/plugin-pos-restaurant/tsconfig.json",
                "packages/plugins/plugin-pos/tsconfig.json",
                "packages/plugins/plugin-procurement/tsconfig.json",
                "packages/plugins/plugin-production/tsconfig.json",
                "packages/plugins/plugin-reviews/tsconfig.json",
                "packages/plugins/plugin-scheduled-orders/tsconfig.json",
                "packages/plugins/plugin-uom/tsconfig.json",
                "packages/plugins/plugin-warehouse/tsconfig.json",
                "packages/plugins/plugin-wishlist/tsconfig.json",
                "packages/sdk/tsconfig.json"
              ],
              "agent_commit_share": 0.76,
              "toolchain_manifests": [],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 18
              },
              {
                "key": "automated_tests",
                "name": "Automated tests",
                "detail": null,
                "points": 22,
                "status": "met",
                "details": [],
                "max_points": 22
              },
              {
                "key": "lint_format_config",
                "name": "Lint / format config",
                "detail": "eslint.config.js, eslint.config.mjs",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "eslint.config.js, eslint.config.mjs"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": "apps/docs/public/scaffold/tsconfig.json, apps/docs/tsconfig.json, apps/restaurant-example/tsconfig.json, apps/saas-example/tsconfig.json, apps/store-example/tsconfig.json, apps/tea-avenue/tsconfig.json, apps/web/tsconfig.json, packages/adapters/adapter-local-storage/tsconfig.json, packages/adapters/adapter-meilisearch/tsconfig.json, packages/adapters/adapter-neon/tsconfig.json, packages/adapters/adapter-pg-search/tsconfig.json, packages/adapters/adapter-pglite/tsconfig.json, packages/adapters/adapter-postgres/tsconfig.json, packages/adapters/adapter-r2/tsconfig.json, packages/adapters/adapter-resend/tsconfig.json, packages/adapters/adapter-s3/tsconfig.json, packages/adapters/adapter-ses/tsconfig.json, packages/adapters/adapter-shopify/tsconfig.json, packages/adapters/adapter-stripe/tsconfig.json, packages/adapters/adapter-tax-manual/tsconfig.json, packages/adapters/adapter-taxjar/tsconfig.json, packages/adapters/adapter-woocommerce/tsconfig.json, packages/cli/templates/starter/tsconfig.json, packages/cli/tsconfig.json, packages/core/tsconfig.json, packages/db/tsconfig.json, packages/import/import-flat/tsconfig.json, packages/import/import-shopify/tsconfig.json, packages/import/import-woocommerce/tsconfig.json, packages/jobs-cloudflare/tsconfig.json, packages/jobs-inngest/tsconfig.json, packages/jobs-pg-boss/tsconfig.json, packages/jobs-trigger/tsconfig.json, packages/plugins/plugin-appointments/tsconfig.json, packages/plugins/plugin-channel-connector/tsconfig.json, packages/plugins/plugin-gift-cards/tsconfig.json, packages/plugins/plugin-layaway/tsconfig.json, packages/plugins/plugin-loyalty/tsconfig.json, packages/plugins/plugin-marketplace/tsconfig.json, packages/plugins/plugin-notifications/tsconfig.json, packages/plugins/plugin-pos-restaurant/tsconfig.json, packages/plugins/plugin-pos/tsconfig.json, packages/plugins/plugin-procurement/tsconfig.json, packages/plugins/plugin-production/tsconfig.json, packages/plugins/plugin-reviews/tsconfig.json, packages/plugins/plugin-scheduled-orders/tsconfig.json, packages/plugins/plugin-uom/tsconfig.json, packages/plugins/plugin-warehouse/tsconfig.json, packages/plugins/plugin-wishlist/tsconfig.json, packages/sdk/tsconfig.json",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "apps/docs/public/scaffold/tsconfig.json, apps/docs/tsconfig.json, apps/restaurant-example/tsconfig.json, apps/saas-example/tsconfig.json, apps/store-example/tsconfig.json, apps/tea-avenue/tsconfig.json, apps/web/tsconfig.json, packages/adapters/adapter-local-storage/tsconfig.json, packages/adapters/adapter-meilisearch/tsconfig.json, packages/adapters/adapter-neon/tsconfig.json, packages/adapters/adapter-pg-search/tsconfig.json, packages/adapters/adapter-pglite/tsconfig.json, packages/adapters/adapter-postgres/tsconfig.json, packages/adapters/adapter-r2/tsconfig.json, packages/adapters/adapter-resend/tsconfig.json, packages/adapters/adapter-s3/tsconfig.json, packages/adapters/adapter-ses/tsconfig.json, packages/adapters/adapter-shopify/tsconfig.json, packages/adapters/adapter-stripe/tsconfig.json, packages/adapters/adapter-tax-manual/tsconfig.json, packages/adapters/adapter-taxjar/tsconfig.json, packages/adapters/adapter-woocommerce/tsconfig.json, packages/cli/templates/starter/tsconfig.json, packages/cli/tsconfig.json, packages/core/tsconfig.json, packages/db/tsconfig.json, packages/import/import-flat/tsconfig.json, packages/import/import-shopify/tsconfig.json, packages/import/import-woocommerce/tsconfig.json, packages/jobs-cloudflare/tsconfig.json, packages/jobs-inngest/tsconfig.json, packages/jobs-pg-boss/tsconfig.json, packages/jobs-trigger/tsconfig.json, packages/plugins/plugin-appointments/tsconfig.json, packages/plugins/plugin-channel-connector/tsconfig.json, packages/plugins/plugin-gift-cards/tsconfig.json, packages/plugins/plugin-layaway/tsconfig.json, packages/plugins/plugin-loyalty/tsconfig.json, packages/plugins/plugin-marketplace/tsconfig.json, packages/plugins/plugin-notifications/tsconfig.json, packages/plugins/plugin-pos-restaurant/tsconfig.json, packages/plugins/plugin-pos/tsconfig.json, packages/plugins/plugin-procurement/tsconfig.json, packages/plugins/plugin-production/tsconfig.json, packages/plugins/plugin-reviews/tsconfig.json, packages/plugins/plugin-scheduled-orders/tsconfig.json, packages/plugins/plugin-uom/tsconfig.json, packages/plugins/plugin-warehouse/tsconfig.json, packages/plugins/plugin-wishlist/tsconfig.json, packages/sdk/tsconfig.json"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": "Dockerfile, lockfile",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "Dockerfile, lockfile"
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "73 of the last 96 commits agent-authored or agent-credited",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 73,
                      "sampled": 96
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "no automated dependency updates observed",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_dependency_automation",
                    "params": {}
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "excellent",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "primary_language": "TypeScript",
              "largest_source_bytes": 59740,
              "source_files_sampled": 804,
              "oversized_source_files": 0
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "TypeScript (statically typed)",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "TypeScript"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "0/804 source files over 60KB",
                "points": 55,
                "status": "met",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 804,
                      "oversized": 0
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          },
          {
            "key": "ai_interfaces",
            "band": "critical",
            "name": "Machine-readable interfaces",
            "note": null,
            "notes": [],
            "value": 20,
            "inputs": {
              "example_dirs": [],
              "has_mcp_signal": true,
              "api_schema_files": []
            },
            "components": [
              {
                "key": "api_schema_openapi_graphql_proto",
                "name": "API schema (OpenAPI/GraphQL/proto)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 40
              },
              {
                "key": "mcp_server",
                "name": "MCP server",
                "detail": null,
                "points": 20,
                "status": "met",
                "details": [],
                "max_points": 20
              },
              {
                "key": "runnable_examples",
                "name": "Runnable examples",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 40
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
      }
    ],
    "metrics_version": "1.13.0"
  },
  "warnings": [
    "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-24T03:58:56.481030Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/a/asyncdotengineering/porulle.svg",
  "full_name": "asyncdotengineering/porulle",
  "license_state": "standard",
  "license_spdx": "MIT"
}

评分是信号,而非担保。 评分反映的是 GitHub 上公开可见的实践——不是代码审计,也不是安全保证。

缺失数据将被剔除并重新归一化权重,绝不按零分计。方法论已版本化并公开:指标 v1.13.0、模式 v0.27.0—— 完整方法论 · 指标知识库.

单项结果在整体记录中的位置: 汇总统计npm.