Registro público
Informe de salud del softwareesquema 0.27.0 · métricas 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 estrellas⑂ 0 forksdesde may 2026Ver en GitHub ↗

asyncdotengineering/porulle tiene un índice de salud de 54 sobre 100, lo que lo sitúa en la banda Moderado. Su puntuación más alta es Vitality (74/100) y la más baja, Community & Adoption (35/100). Se actualizó por última vez hace 5 días. Una sola persona concentra la mayor parte del trabajo reciente.

54
global / 100
Moderado

Índice de salud del software

Las métricas se agrupan en categorías ponderadas sobre una escala de 1 a 100. El resultado global parte de su media; cuando la evidencia pública activa la Política de Jurisdicciones de Alto Riesgo, la calificación se ajusta y recibe el límite 49 (En riesgo). Preparación para IA queda fuera.

54
Excelente85-100Ejemplar; cumple prácticamente todos los criterios evaluados
Bueno70-84Saludable; carencias menores
Moderado50-69Aceptable con carencias notables; se recomienda revisión
En riesgo30-49Debilidades significativas; su adopción exige cautela
Crítico1-29Problemas graves (proyecto abandonado, un solo mantenedor, sin higiene)
VitalidadComunidad yAdopciónSostenibilidady GobernanzaCalidad deIngenieríaSeguridadPreparaciónpara IA

Perfil de puntuación

Cada eje es una categoría. La forma importa más que la media: un proyecto sano llena toda la figura, mientras que un perfil de picos y cráteres indica que la fortaleza en una dimensión enmascara el riesgo en otra.

Titularidad

0 seguidores9 repositorios públicosdesde abr 2023

Este repositorio está respaldado por una organización: una custodia compartida y responsable que puede sobrevivir a cualquier mantenedor individual.

Ecosistemas de paquetes

RegistroPaqueteVersiónDescargas / mesVersionesÚltima publicación
npm@porulle/db0.10.4140911hace 5 días
npm@porulle/cli0.10.4124811hace 5 días
npm@porulle/sdk0.10.4118211hace 5 días
npm@porulle/core0.10.4419411hace 5 días
npm@porulle/jobs-inngest0.10.47786hace 5 días
npm@porulle/jobs-pg-boss0.10.47666hace 5 días
npm@porulle/jobs-trigger0.10.47386hace 5 días
npm@porulle/jobs-cloudflare0.10.47636hace 5 días

Métricas por categoría

Vitalidad

¿Está vivo el proyecto: se escribe código y se publican versiones?

74Bueno · 22% del índice global
Cómo se puntúa
36/36Recencia de push — último push hace 5 días
3.5/36Cadencia de commits — 5/52 semanas con commits
17.8/18Volumen de commits — 96 commits en el último año
0/10OpenSSF Scorecard: Maintained — project was created within the last 90 days. Please review its contents carefully
Datos de entrada utilizados
commits_last_year96
human_commit_share1
days_since_last_push5
active_weeks_last_year5
Cómo se puntúa
27/27Publica versiones — 2 versiones publicadas
36/36Recencia de las versiones — última versión hace 39 días
27/27Cadencia de publicación — una versión cada ~0 días
0/10OpenSSF Scorecard: Signed-Releases — sin datos
Datos de entrada utilizados
releases_count2
latest_release_tagv0.6.0
releases_from_tagsno
days_since_latest_release39
mean_days_between_releases0
Excluidos de la puntuación (sin datos o no aplicable): OpenSSF Scorecard: Signed-Releases. Los pesos restantes se han renormalizado.

Comunidad y Adopción

¿Tiene el proyecto usuarios, descargas, atención y unas condiciones acogedoras para quienes contribuyen?

35En riesgo · 18% del índice global
Cómo se puntúa
0/60Estrellas — 0 estrellas
0/25Forks — 0 forks
0/15Observadores — 0 observadores
Datos de entrada utilizados
forks0
stars0
watchers0
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
Cómo se puntúa
22.5/22.5README
22.5/22.5Licencia — licencia reconocida (MIT)
0/18Guía CONTRIBUTING
0/13.5Código de conducta
0/7.2Plantilla de issues
0/6.3Plantilla de PR
Datos de entrada utilizados
has_readme
has_license
has_contributingno
has_issue_templateno
has_code_of_conductno
has_pull_request_templateno
Cómo se puntúa
53.9/80Descargas mensuales — 11.078 descargas/mes en npm
0/20Dependientes en el registro — no lo informa este ecosistema
Datos de entrada utilizados
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
Excluidos de la puntuación (sin datos o no aplicable): Dependientes en el registro. Los pesos restantes se han renormalizado.

Sostenibilidad y Gobernanza

¿Sobrevivirá el proyecto a sus personas: factor bus, capacidad de respuesta, quién lo respalda y mantenimiento del paquete?

56Moderado · 24% del índice global
Cómo se puntúa
9/54Factor bus — la mitad de los commits recae en 1 contribuyente(s)
0/22.5Distribución de commits — el principal contribuyente firma el 100% de los commits
1.4/13.5Amplitud de contribuyentes — 1 contribuyentes
3/10OpenSSF Scorecard: Contributors — project has 1 contributing companies or organizations -- score normalized to 3
Datos de entrada utilizados
bus_factor1
contributors_sampled1
top_contributor_share1
Cómo se puntúa
46.8/46.8Resolución de issues — 100% de issues cerradas
38.2/38.3Aceptación de PR — 13/13 PR decididos fusionados
0/15OpenSSF Scorecard: Code-Review — Found 0/13 approved changesets -- score normalized to 0
Datos de entrada utilizados
merged_prs13
open_issues0
closed_issues55
issue_closed_ratio1
closed_unmerged_prs0
Cómo se puntúa
30/30Respaldo de la propiedad — propiedad de una organización
0/20Dominio verificado
0/25Alcance del propietario — 0 seguidores de asyncdotengineering
13.8/25Trayectoria — 9 repos públicos, cuenta de ~3 años
Datos de entrada utilizados
followers0
owner_typeOrganization
is_verified
owner_loginasyncdotengineering
public_repos9
account_age_days1197
Cómo se puntúa
25/25Publicado y resoluble — 8 paquete(s) en npm
35/35Recencia de publicación — última publicación hace 5 días
20/20Historial de versiones — 11 versiones en el registro
20/20No obsoleto — activo, ni obsoleto ni retirado
Datos de entrada utilizados
packages@porulle/db, @porulle/cli, @porulle/sdk, @porulle/core, @porulle/jobs-inngest, @porulle/jobs-pg-boss, @porulle/jobs-trigger, @porulle/jobs-cloudflare
ecosystemsnpm
any_deprecatedno
min_days_since_publish5

Calidad de Ingeniería

¿Existen unas prácticas mínimas de ingeniería y documentación?

60Moderado · 20% del índice global
Cómo se puntúa
0/24Flujos de trabajo de CI
24/24Pruebas presentes
16/16Configuración de linter — eslint.config.js, eslint.config.mjs
0/9.6Hooks de pre-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
Datos de entrada utilizados
has_cino
has_tests
has_editorconfigno
has_linter_config
has_precommit_configno

Documentación

90Excelente
Cómo se puntúa
30/30README
25/25Directorio de documentación
15/15Sitio de documentación / página del proyecto — https://porulle-docs.vercel.app
10/10Descripción del repositorio
0/10Topics
10/10Wiki
Datos de entrada utilizados
topics
has_wiki
homepagehttps://porulle-docs.vercel.app
has_readme
has_docs_dir
has_description

Seguridad

¿Son sólidas las prácticas visibles de seguridad y de cadena de suministro, sin exposición jurisdiccional de alto riesgo sin resolver?

37En riesgo · 16% del índice global
Cómo se puntúa
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 — sin datos
0/7.5Dependency-Update-Tool — no update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5Licencia — license file detected
0/7.5Maintained — project was created within the last 90 days. Please review its contents carefully
0/5Packaging — sin datos
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 — sin datos
0/7.5Token-Permissions — sin datos
0/7.5Vulnerabilities — 54 existing vulnerabilities detected
Datos de entrada utilizados
sourceopenssf_scorecard
checks_evaluated14
scorecard_versionv5.5.0
checks_inconclusive4
scorecard_aggregate2,1
Excluidos de la puntuación (sin datos o no aplicable): dangerous_workflow, packaging, signed_releases, token_permissions. Los pesos restantes se han renormalizado.
Cómo se puntúa
35/35Dependencias directas libres de avisos conocidos — ninguna dependencia directa tiene un aviso conocido
25/25Dependencias indirectas libres de avisos conocidos — ninguna dependencia indirecta tiene un aviso conocido
0/40Sin avisos pendientes — ningún aviso tiene fecha de publicación
Datos de entrada utilizados
sourceosv
advisories0
affected_packages0
assessed_packages57
unassessed_packages0
affected_by_severitynone
direct_affected_packages0
Excluidos de la puntuación (sin datos o no aplicable): Sin avisos pendientes. Los pesos restantes se han renormalizado. Se cotejó el cierre de dependencias en tiempo de ejecución de npm:@porulle/db@0.10.4 —lo que arrastra la instalación del paquete publicado—: 57 paquetes. No se analiza la alcanzabilidad.

Preparación para IA

¿Hasta qué punto está el repositorio preparado para desarrollarse y mantenerse con agentes de codificación de IA? Es una insignia independiente y experimental — peso 0,0, de modo que se presenta por separado y no afecta a la puntuación de salud global.

69Moderado · 0% del índice global
Cómo se puntúa
45/45Instrucciones para agentes — .agents/factory/workers/claude.md, .archive/research/AGENTS.md, CLAUDE.md
0/15Documentación legible por máquinas (llms.txt)
40/40Historial de commits legible — 96 de 96 commits humanos declaran su intención (asunto estructurado o cuerpo explicativo)
Datos de entrada utilizados
has_llms_txtno
legible_history_share1
agent_instruction_files.agents/factory/workers/claude.md, .archive/research/AGENTS.md, CLAUDE.md
agent_instruction_max_bytes13.046
Cómo se puntúa
0/18Arranque con un solo comando
22/22Pruebas automatizadas
11/11Configuración de lint / formato — eslint.config.js, eslint.config.mjs
11/11Verificación estática de tipos — 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/10Entorno reproducible — Dockerfile, lockfile
10/10Práctica demostrada con agentes — 73 de los últimos 96 commits con autoría o crédito de agente
0/8Mantenimiento automatizado — no se observan actualizaciones automáticas de dependencias
0/10OpenSSF Scorecard: Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
Datos de entrada utilizados
has_nixno
has_tests
lockfilespnpm-lock.yaml
has_dockerfile
typed_language
bootstrap_files
has_devcontainerno
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
Cómo se puntúa
45/45Código verificable por tipos — TypeScript (tipado estático)
55/55Tamaños de archivo manejables — 0/804 archivos fuente de más de 60 KB
Datos de entrada utilizados
primary_languageTypeScript
largest_source_bytes59.740
source_files_sampled804
oversized_source_files0
Cómo se puntúa
0/40Esquema de API (OpenAPI/GraphQL/proto)
20/20Servidor MCP
0/40Ejemplos ejecutables
Datos de entrada utilizados
example_dirs
has_mcp_signal
api_schema_files

Datos clave

0estrellas de GitHub
1contribuidores
96commits en los últimos 12 meses
5días desde el último push
2versiones publicadas
1factor bus
0issues abiertas
npmecosistemas de paquetes

Advertencias de recopilación de datos

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

Más detalle

OpenSSF Scorecard 2.1 / 10
2.1agregado

Evaluación de seguridad independiente y agnóstica en cuanto a herramientas, procedente del proyecto de código abierto OpenSSF Scorecard. Cada comprobación premia una práctica de seguridad, no la herramienta de un proveedor concreto. Las comprobaciones que Scorecard no pudo determinar se marcan como n/d y se excluyen de la puntuación de seguridad (nunca se cuentan como cero).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
n/dDangerous-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
n/dPackagingpackaging 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
n/dSigned-Releasesno releases found
n/dToken-PermissionsNo tokens found
0Vulnerabilities54 existing vulnerabilities detected
Dependencias directas 74
RegistroPaqueteRestricción de versiónManifiesto
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
Todas las dependencias no recopilado

No fue posible recopilar el conjunto de dependencias resuelto para este informe: GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository

Avisos de dependencias 0

Instalar npm:@porulle/db@0.10.4 arrastra 57 paquetes, directos y transitivos: 0 tienen avisos conocidos, de los cuales 0 son dependencias directas.

Ningún aviso conocido afecta a las dependencias evaluadas.

Un aviso significa que la versión registrada en el grafo de dependencias cae dentro del rango afectado de un aviso. No se analiza la alcanzabilidad, y el grafo incluye fijaciones de desarrollo y prueba: un hallazgo puede referirse al utillaje y no al software distribuido.

Informe JSON sin procesar legible por máquina
{
  "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"
}

Las puntuaciones son señales, no garantías. Reflejan prácticas públicamente visibles en GitHub; no son una auditoría de código ni una garantía de seguridad.

Los datos ausentes se excluyen y los pesos se renormalizan; nunca se puntúan como cero. La metodología es versionada y abierta: métricas v1.13.0, esquema v0.27.0 — metodología completa · wiki de métricas.

Cómo se sitúa un resultado dentro del registro general: estadísticas agregadasnpm.