公开记录
软件健康报告模式 0.27.0 · 指标 1.13.0 · 2026-07-25 12:41 UTC

Spooled-Cloud / spooled-sdk-nodejs

Official Node.js/TypeScript SDK for Spooled. Type-safe, async/await support for Express, Next.js, vanilla Node.js. Retry logic, circuit breaker.

TypeScriptApache-2.0★ 5 星标⑂ 0 复刻始于 2025年12月在 GitHub 上查看 ↗

Spooled-Cloud/spooled-sdk-nodejs 的健康指数为 100 分中的 60 分,处于「中等」区间。 其得分最高的类别是Engineering Quality(88/100),最低的是Community & Adoption(35/100)。 最近一次更新在 5 天前。 近期的大部分工作由 1 位贡献者完成。

60
总分 / 100
中等

软件健康指数

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

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

评分画像

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

所有权

3 关注者8 个公开仓库始于 2025年12月

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

软件包生态系统

注册表软件包版本月下载量版本数最近发布标签
npm@spooled/sdk1.0.402,076305 天前spooledjob-queuetask-queuebackground-jobswebhookscronschedulerworkflow

按类别列示的指标

活力

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

82良好 · 占总体的 22%
评分方式
36/36推送新近度 — 最近一次推送于 5 天前
5.5/36提交节奏 — 52 周中有 8 周有提交
18/18提交量 — 最近一年 110 次提交
10/10OpenSSF Scorecard:Maintained — 30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
所用输入
commits_last_year110
human_commit_share1
days_since_last_push5
active_weeks_last_year8

发布纪律

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

社区与采用

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

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

社区健康

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

可持续性与治理

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

36存在风险 · 占总体的 24%
评分方式
9/54巴士系数 — 1 位贡献者贡献了半数提交
0/22.5提交分布 — 头号贡献者编写了 100% 的提交
1.4/13.5贡献者广度 — 1 位贡献者
6/10OpenSSF Scorecard:Contributors — project has 2 contributing companies or organizations -- score normalized to 6
所用输入
bus_factor1
contributors_sampled1
top_contributor_share1
评分方式
0/46.8议题解决 — 没有议题或无数据
0/38.3PR 接受 — 没有已裁定的拉取请求或无数据
0/15OpenSSF Scorecard:Code-Review — Found 0/30 approved changesets -- score normalized to 0
所用输入
merged_prs0
open_issues0
closed_issues0
issue_closed_ratio
closed_unmerged_prs0
已排除计分(无数据或不适用):议题解决, PR 接受。 其余权重已重新归一化。
评分方式
30/30所有权背书 — 组织持有
0/20已验证域名
4.3/25所有者影响力 — Spooled-Cloud 有 3 位关注者
8.2/25既往记录 — 8 个公开仓库,账户约 0 年
所用输入
followers3
owner_typeOrganization
is_verified
owner_loginSpooled-Cloud
public_repos8
account_age_days228
评分方式
25/25已发布且可解析 — npm 上有 1 个软件包
35/35发布时效 — 最近一次发布于 5 天前
20/20版本历史 — 30 个已发布版本
20/20未被弃用 — 活跃,未被弃用或撤回
所用输入
packages@spooled/sdk
ecosystemsnpm
any_deprecated
min_days_since_publish5

工程质量

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

88优秀 · 占总体的 20%

工程实践

80良好
评分方式
24/24CI 工作流 — 1 个工作流
24/24存在测试
16/16Linter 配置 — eslint.config.js
0/9.6Pre-commit 钩子
0/6.4.editorconfig
0/20OpenSSF Scorecard:CI-Tests — 无数据
所用输入
has_ci
has_tests
has_editorconfig
has_linter_config
has_precommit_config
已排除计分(无数据或不适用):OpenSSF Scorecard:CI-Tests。 其余权重已重新归一化。

文档

100优秀
评分方式
30/30README
25/25文档目录
15/15文档 / 主页站点 — https://spooled.cloud
10/10仓库描述
10/10主题标签 — 9 个主题标签
10/10Wiki
所用输入
topicsasync, client-library, javascript, nodejs, npm, sdk, type-safe, typescript, webhook
has_wiki
homepagehttps://spooled.cloud
has_readme
has_docs_dir
has_description

安全

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

62中等 · 占总体的 16%

安全态势

53中等
评分方式
7.5/7.5Binary-Artifacts — no binaries found in the repo
2.2/7.5Branch-Protection — branch protection is not maximal on development and all release branches
0/2.5CI-Tests — 无数据
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
0/7.5Code-Review — Found 0/30 approved changesets -- score normalized to 0
1.5/2.5Contributors — project has 2 contributing companies or organizations -- score normalized to 6
10/10Dangerous-Workflow — no dangerous workflow patterns detected
0/7.5Dependency-Update-Tool — no update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5许可证 — license file detected
7.5/7.5Maintained — 30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
5/5Packaging — packaging workflow detected
1/5Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 2
0/5SAST — no SAST tool detected
0/5Security-Policy — security policy file not detected
0/7.5Signed-Releases — 无数据
7.5/7.5Token-Permissions — GitHub workflow tokens follow principle of least privilege
5.2/7.5Vulnerabilities — 3 existing vulnerabilities detected
所用输入
sourceopenssf_scorecard
checks_evaluated16
scorecard_versionv5.5.0
checks_inconclusive2
scorecard_aggregate5.3
已排除计分(无数据或不适用):ci_tests, signed_releases。 其余权重已重新归一化。
评分方式
35/35直接依赖不含已知公告 — 没有直接依赖携带已知公告
25/25间接依赖不含已知公告 — 没有间接依赖携带已知公告
0/40没有长期未处理的公告 — 没有公告带有发布日期
所用输入
sourceosv
advisories0
affected_packages0
assessed_packages36
unassessed_packages0
affected_by_severitynone
direct_affected_packages0
已排除计分(无数据或不适用):没有长期未处理的公告。 其余权重已重新归一化。 比对的是 npm:@spooled/sdk@1.0.40 的运行时依赖闭包——安装已发布的软件包时真正被拉取进来的内容——共 36 个软件包。 未对可达性进行分析。

AI 就绪度

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

75良好 · 占总体的 0%
评分方式
45/45代理指令 — .cursor/rules/kb-sync.mdc, AGENTS.md
0/15机器可读文档(llms.txt)
40/40可读的提交历史 — 100 次人类提交中有 98 次说明了意图(结构化标题或解释性正文)
所用输入
has_llms_txt
legible_history_share0.98
agent_instruction_files.cursor/rules/kb-sync.mdc, AGENTS.md
agent_instruction_max_bytes502
评分方式
0/18一条命令的引导启动
22/22自动化测试
11/11Lint / 格式化配置 — eslint.config.js
11/11静态类型检查 — tsconfig.json
10/10可复现环境 — lockfile
0/10已体现的代理实践 — 最近 100 次提交中没有代理编写的提交
0/8自动化维护 — 未观察到自动依赖更新
2/10OpenSSF Scorecard:Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 2
所用输入
has_nix
has_tests
lockfilespackage-lock.json
has_dockerfile
typed_language
bootstrap_files
has_devcontainer
has_linter_config
typecheck_configstsconfig.json
agent_commit_share0
toolchain_manifests
dependency_bot_commit_share0
评分方式
45/45可类型检查的代码 — TypeScript(静态类型)
54.4/55可控的文件大小 — 采样的 96 个源文件中有 1 个超过 60KB
所用输入
primary_languageTypeScript
largest_source_bytes137,922
source_files_sampled96
oversized_source_files1
评分方式
40/40API 模式(OpenAPI/GraphQL/proto) — proto/spooled.proto
0/20MCP 服务器
40/40可运行示例 — examples
所用输入
example_dirsexamples
has_mcp_signal
api_schema_filesproto/spooled.proto

关键数据

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

数据采集警告

  • Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token
  • GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository

更多细节

OpenSSF Scorecard 5.3 / 10
5.3综合

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

10Binary-Artifactsno binaries found in the repo
3Branch-Protectionbranch protection is not maximal on development and all release branches
不适用CI-Testsno pull request found
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 0/30 approved changesets -- score normalized to 0
6Contributorsproject has 2 contributing companies or organizations -- score normalized to 6
10Dangerous-Workflowno dangerous workflow patterns detected
0Dependency-Update-Toolno update tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
10Maintained30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
10Packagingpackaging workflow detected
2Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 2
0SASTno SAST tool detected
0Security-Policysecurity policy file not detected
不适用Signed-Releasesno releases found
10Token-PermissionsGitHub workflow tokens follow principle of least privilege
7Vulnerabilities3 existing vulnerabilities detected
直接依赖 4
注册表软件包版本约束清单文件
npm@grpc/grpc-js^1.14.3package.json
npm@grpc/proto-loader^0.8.0package.json
npmeventsource^3.0.7package.json
npmws^8.20.0package.json
全部依赖 未采集

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

依赖安全公告 0

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

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

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

原始 JSON 报告 机器可读
{
  "data": {
    "repo": {
      "topics": [
        "async",
        "client-library",
        "javascript",
        "nodejs",
        "npm",
        "sdk",
        "type-safe",
        "typescript",
        "webhook"
      ],
      "is_fork": false,
      "size_kb": 1069,
      "has_wiki": true,
      "homepage": "https://spooled.cloud",
      "languages": {
        "Shell": 1352,
        "JavaScript": 3032,
        "TypeScript": 590021
      },
      "pushed_at": "2026-07-19T14:47:15Z",
      "created_at": "2025-12-09T14:06:40Z",
      "owner_type": "Organization",
      "updated_at": "2026-07-19T14:47:18Z",
      "description": "Official Node.js/TypeScript SDK for Spooled. Type-safe, async/await  support for Express, Next.js, vanilla Node.js. Retry logic, circuit breaker.",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "Apache-2.0",
      "default_branch": "main",
      "license_spdx_raw": "Apache-2.0",
      "primary_language": "TypeScript",
      "significant_languages": [
        "TypeScript"
      ]
    },
    "owner": {
      "blog": "https://spooled.cloud",
      "name": "Spooled Cloud",
      "type": "Organization",
      "login": "Spooled-Cloud",
      "company": null,
      "location": "Canada",
      "followers": 3,
      "avatar_url": "https://avatars.githubusercontent.com/u/248554435?v=4",
      "created_at": "2025-12-08T20:51:10Z",
      "is_verified": null,
      "public_repos": 8,
      "account_age_days": 228
    },
    "license": {
      "state": "standard",
      "spdx_id": "Apache-2.0",
      "raw_spdx": "Apache-2.0",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v1.0.40",
          "kind": "patch",
          "published_at": "2026-07-19T14:47:54Z"
        },
        {
          "tag": "v1.0.37",
          "kind": "patch",
          "published_at": "2026-07-14T20:58:51Z"
        },
        {
          "tag": "v1.0.36",
          "kind": "patch",
          "published_at": "2026-07-13T17:06:55Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "06d0f5ddad724239cef7b8b598fb0fbaa45779c0",
          "body": "Worker detail typing (queueNames/updatedAt, nullable workerType/version), gRPC unary timeout + error mapping, worker progress debug output, example typecheck coverage.",
          "is_bot": false,
          "headline": "chore(release): 1.0.40",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2026-07-19T14:47:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fe3b91372234fdac0dc80788b5fdedb21f2630e3",
          "body": "… notes\n\nWorker.workerType and Worker.version are serialized as explicit null by the\nbackend when unset; type them string | null so strict consumers handle the\nruntime value. Correct the KB parity/findings notes that claimed the backend\npersists job progress for the Go SDK — no such endpoint exists.",
          "is_bot": false,
          "headline": "fix(types): model backend nulls on Worker and correct progress parity…",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2026-07-19T13:40:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "79cde52234a9336b933695c641a088118a3f8193",
          "body": "Match backend REST worker detail public fields so TypeScript consumers see multi-queue membership and last update timestamps.",
          "is_bot": false,
          "headline": "fix(workers): type queueNames and updatedAt",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2026-07-17T14:03:15Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e7ea82f2a77e09e84dab0f046337757babe440be",
          "body": null,
          "is_bot": false,
          "headline": "fix(examples): sync workflow contracts",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2026-07-16T20:36:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b0dcda8aae315897936fc1da2e72feb73dc8f353",
          "body": "Pass configured timeouts to unary gRPC calls and map gRPC statuses into SDK errors for consistent caller behavior.",
          "is_bot": false,
          "headline": "fix(grpc): apply Node unary deadlines",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2026-07-16T19:34:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8b205dc946bfd20ee7919ffe4fb25ce6d6601065",
          "body": "Align the repo with its declared Prettier gate so format checks\npass before publish or release verification.",
          "is_bot": false,
          "headline": "style: format Node SDK",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2026-07-16T18:38:19Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "237bcb404d38e863810fbe48caaa08d7c2bb839f",
          "body": "Publish diagnostics must avoid exposing token-bearing npm config\nwhile keeping release docs aligned with 1.0.39.",
          "is_bot": false,
          "headline": "ci: stop printing npm config",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2026-07-16T18:35:04Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9677aeeeab1b79442df96ee2f97e493e88e520e5",
          "body": "tsup flattens loader into dist/index.js so ../../proto pointed above the package root and client.grpc threw ENOENT. Try ../proto then ../../proto.",
          "is_bot": false,
          "headline": "fix(grpc): resolve proto path from bundled dist (1.0.39)",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2026-07-15T02:20:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "89effaa886fb7befc41b9c5a5757ed1460d331c7",
          "body": null,
          "is_bot": false,
          "headline": "docs(ai): refresh knowledge versions to live 0.1.107 / SDK tips",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2026-07-15T02:08:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b33eb15ae612e5948814be3b6a001b25a768d743",
          "body": null,
          "is_bot": false,
          "headline": "chore(agents): add alwaysApply KB sync Cursor rule",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2026-07-15T01:18:29Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "724f36f6b6b389373232d32407e974837c4fe306",
          "body": "Avoid proto-loader zero defaults on maxRetries/timeoutSeconds. KB sync rule.",
          "is_bot": false,
          "headline": "fix(grpc): omit unset enqueue ints; release 1.0.38",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2026-07-15T01:18:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0d9cdc8d79753620a032a0649cf693509733264e",
          "body": null,
          "is_bot": false,
          "headline": "docs(ai): add SDK knowledge base and contract notes",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2026-07-15T01:13:15Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ef99d4959f4ad85454915ffae3da61ffcb2394db",
          "body": "Sync npm/runtime version surfaces after gRPC certs doc cleanup.",
          "is_bot": false,
          "headline": "chore(release): prepare v1.0.37",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2026-07-14T20:55:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4d3a61194de259928b0b662b89cbc95da57f3213",
          "body": "Point at Compose-generated grpc_tls volume instead.",
          "is_bot": false,
          "headline": "docs(grpc): stop recommending historical ./certs/ PEMs",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2026-07-14T20:05:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "907f88306c9539bc800981f81736d84534ed81c3",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): prepare v1.0.36",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2026-07-13T17:01:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cbef824ee81abc9002b0dbcd999a621dae5d3d42",
          "body": "Convert plain JavaScript payload/result objects to google.protobuf.Struct before unary gRPC calls and decode Struct responses back to plain objects. This prevents enqueue/complete payloads from serializing as empty objects.",
          "is_bot": false,
          "headline": "fix(grpc): encode Struct payloads",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2026-07-13T15:51:40Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "be5e2ee0de34b508fa4a8fcb6e4837798b4ce681",
          "body": "Preserve Node 18 installs by using EventSource 3, reject failed WebSocket upgrades instead of leaving connect pending, keep reconnect attempts alive after token acquisition failures, and prevent custom retry predicates from replaying unsafe writes.",
          "is_bot": false,
          "headline": "fix(realtime): keep reconnects safe",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2026-07-13T15:49:48Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "af4828c32c5c8db48ea34c7d976857b27f98e036",
          "body": null,
          "is_bot": false,
          "headline": "fix(release): verify npm artifact identity",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2026-07-12T18:42:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f74bbb60e9c3bea30b615b1aa7b05670d70ab6d3",
          "body": null,
          "is_bot": false,
          "headline": "docs: align SDK contracts and examples",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2026-07-12T17:38:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "268b1af9c4422bc7bda171de59389be8b21645e9",
          "body": null,
          "is_bot": false,
          "headline": "fix(worker): fence overlapping lease executions",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2026-07-12T15:19:32Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "93ff7ec8b6a1cf83538f5fa3f020fc0abaf837f7",
          "body": "The claim response now surfaces the backend's lease_id fencing token\n(ClaimedJob.leaseId), and the worker echoes it on complete/fail/heartbeat\nso a stale lease — even from the same worker after a reclaim — is rejected\nby the server with 409 LEASE_EXPIRED instead of silently winning. Requires\nbackend\n[…]\nDKs keep the legacy worker_id fence. Proto updated with the\nlease_id fields (Job=19, Complete=4, Fail=5, RenewLease=4) for gRPC parity.\n\nAlso fixes the stale hardcoded worker default version (1.0.26).",
          "is_bot": false,
          "headline": "feat(worker,jobs): capture and echo lease_id fencing token (audit F9)",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2026-07-11T20:51:53Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ba7435acbc886a8409123c352b79aa3175614b61",
          "body": "…n-JSON error text\n\nThe realtime API was broken against the live backend:\n\n- The backend serializes RealtimeEvent with the PascalCase enum variant name\n  as the `type` tag (JobCompleted, JobStatusChange, QueueStats, ...), but the\n  SDK dispatched typed handlers by dotted names (job.completed, ...), \n[…]\ner-Agent synced from a stale 1.0.31 to 1.0.33.\n\nAdds unit tests for PascalCase->dotted dispatch, prompt (ack-free) subscribe\nwith the {cmd,queue,job_id} shape, and non-JSON error message preservation.",
          "is_bot": false,
          "headline": "fix(realtime): align typed events + subscribe to backend; preserve no…",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2026-07-09T20:44:59Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "6f5d92bffb495426fa7edf5afbbe497011894fac",
          "body": "…CI runs Node 20)",
          "is_bot": false,
          "headline": "ci: pin npm@11 for Trusted Publishing (npm@latest 12+ needs Node 22, …",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2026-07-09T04:09:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7a8dab6d61de102f7b60b272b94062de943b2dc7",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): trim credentials (v1.0.32)",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2026-07-09T03:58:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1d0bddc1a1542364858e2be2af5c8d85aab967e9",
          "body": "undici's fetch rejects `Authorization: Bearer <key>\\n` with an opaque\n`TypeError: HeaderValue` error, and users routinely load keys from\n`.env` files that carry a trailing newline. resolveConfig now normalizes\napiKey, accessToken, refreshToken, and adminKey (treating an all-\nwhitespace value as unde\n[…]\no match the Go, PHP, and Python SDKs.\n\nAdds unit tests covering trailing newline, surrounding whitespace,\nwhitespace-only inputs, and a check that the resulting Authorization\nheader contains no CR/LF.",
          "is_bot": false,
          "headline": "fix: trim whitespace from API keys and tokens in resolveConfig",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2026-07-09T03:38:53Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "dd124229d12808dd6c6366aa2d7150bbc7b5503f",
          "body": "… cron 5-field note",
          "is_bot": false,
          "headline": "docs(readme): quota error is now 429 + code QUOTA_EXCEEDED (was 403);…",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2026-07-09T02:35:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a0c964659af1b4eb6c57495fac06d4f9498c16dc",
          "body": null,
          "is_bot": false,
          "headline": "chore: sync SDK_VERSION/User-Agent to 1.0.31",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2026-07-08T13:55:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "984741ead199830675924bb552ae2b922c2bb725",
          "body": "The token provider passed to client.realtime() minted a fresh JWT via\nPOST /api/v1/auth/login on every (re)connect. Under a reconnect storm this\ntripped the login rate limit (429) and realtime could never recover.\n\nThe client now caches the JWT at the client level (shared across reconnects)\nand reus\n[…]\nrevoked token is replaced\ninstead of replayed into a reconnect loop.\n\nAdds unit tests for the login-count/expiry/force-refresh behavior and the\nJWT exp decoding, and for the WS auth-failure detection.",
          "is_bot": false,
          "headline": "fix(realtime): cache JWT across WebSocket reconnects (1.0.31)",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2026-07-08T13:49:56Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1548f97a7d52e1d707f55e31caba479f6b5a07c2",
          "body": "…ect was off by default\n\nSame root cause as the debug TypeError: autoReconnect/maxReconnectAttempts/\nreconnectDelay/maxReconnectDelay were defaulted before the ...options spread, so\nthe undefined values SpooledRealtime forwards overwrote them. autoReconnect\nresolved to undefined (falsy), disabling reconnect despite the documented default\nof true. Defaults now applied after the spread. +6 regression tests.",
          "is_bot": false,
          "headline": "fix(realtime): reconnect defaults clobbered by undefined; auto-reconn…",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2026-07-08T11:20:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b8485f270a1d9e1a122cc3d02de9825ed03d6087",
          "body": "…emplate (v1.0.30)\n\nclient.realtime() threw `TypeError: this.options.debug is not a function`\non connect for any client built without a `debug` option — the normal,\ndefault case — leaving realtime unusable out of the box.\n\nRoot cause: SpooledRealtime forwards `debug: undefined`, and the WebSocket\nan\n[…]\nion tests covering WebSocket and SSE clients (and the\nSpooledRealtime wrapper) constructed with no debug option and with an\nexplicit `debug: undefined`, asserting debug is callable and does not throw.",
          "is_bot": false,
          "headline": "fix(realtime): make debug always callable; document schedule payloadT…",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2026-07-08T11:17:58Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "23e722734b52955c14de117d4ded6665dcea7d42",
          "body": "…y (v1.0.29)\n\nRemediation from a multi-agent SDK bug hunt (verified against the live backend).\nRealtime WebSocket now authenticates via a JWT in ?token= (was an ignored\nheader), SSE uses the correct query param, opaque job payloads are transmitted\nverbatim, non-idempotent POSTs are not blindly retried, the circuit breaker no\nlonger trips on client 4xx, and Retry-After is honored. See CHANGELOG for the\nfull list.",
          "is_bot": false,
          "headline": "fix: realtime auth, payload preservation, retry/circuit-breaker safet…",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2026-07-08T07:39:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6d81d76fa69261d69c3df41e9149ff79d3221ada",
          "body": "Bump to 1.0.28. Resolve high-severity advisories via npm audit fix and correct the API key prefix and error-handling examples in the README.",
          "is_bot": false,
          "headline": "chore(release): dependency security fixes & README corrections (v1.0.28)",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2026-07-07T13:30:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "664d823a0f11a96119e7aed25f1fc98674e64cbe",
          "body": "- API keys are sp_live_/sp_test_ (sk_ is legacy-accepted only); all\n  examples updated.\n- The error-handling snippets imported LimitExceededError and read\n  error.current/limit/upgradeTo — none of which exist. Plan-limit\n  responses are HTTP 403 and surface as AuthorizationError; examples\n  now use the real classes and fields.\n\nAudit ref: audit-memos/09-consistency.md C2/C9 (R16).",
          "is_bot": false,
          "headline": "docs: fix key prefix and error-handling examples in README",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2026-07-07T05:32:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5022c497fd351e5345b8323758e3aac76b98345a",
          "body": "Bumps within existing semver ranges (lockfile only):\n- @grpc/grpc-js 1.14.3 -> 1.14.4\n- protobufjs 7.5.6 -> 7.6.5 (DoS via recursive descriptor expansion,\n  Any expansion DoS, property shadowing)\n- ws 8.20.0 -> 8.21.0 (uninitialized memory disclosure, fragment DoS)\n- vite (dev) to a patched 8.x\n\nnpm audit is clean; unit tests and build pass.\n\nAudit ref: audit-memos/11-secrets-deps.md (R8).",
          "is_bot": false,
          "headline": "fix(deps): resolve high-severity advisories via npm audit fix",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2026-07-07T04:39:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4b5a9d9a401c864a910541ecdeb05180563bc824",
          "body": "Release content:\n- Bump @spooled/sdk to 1.0.27.\n- Refresh safe direct runtime and development dependencies, including ws and Vitest tooling.\n- Fix SSE client EventSource leak: handleDisconnect now calls close() before\n  nulling the reference, preventing duplicate connections on reconnect.\n- Replace \n[…]\n generation.\n\nCI updates:\n- Update publish workflow to actions/checkout@v6 and actions/setup-node@v6.\n\nVerified: npm ci; npm run lint; npm run typecheck; npm run build; npm test; npm audit --omit=dev.",
          "is_bot": false,
          "headline": "chore: refresh Node SDK dependencies and fix SSE leak (v1.0.27)",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2026-05-05T22:16:17Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "3d75f03a50c1a3589cfa1490ab9a5d31cdd40b84",
          "body": null,
          "is_bot": false,
          "headline": "Update README.md",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-29T15:45:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f1fbf59f2a0c3e6e661e9d6440f5de94e3a57f26",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): v1.0.26",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-21T17:06:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a80ebfcae958a6359f787389aaa2e71fdf775676",
          "body": "…require",
          "is_bot": false,
          "headline": "fix: ESM compatibility for WebSocket - use dynamic import instead of …",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-21T16:34:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cb4a564fcdf92b816bb28658c49aea7afaa952ea",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): v1.0.25",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-21T16:05:54Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4dbb77f8b54d6681fa047647ea24a9d06cc6247d",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): v1.0.24",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-21T16:05:19Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ad5b0b4513eb2da2add5afebaebc4c857890bf9c",
          "body": null,
          "is_bot": false,
          "headline": "docs: add Live Demo (SpriteForge) link",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-21T15:51:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8cb0881feea5a20cafd87c0020b0c82b0bd74c61",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): v1.0.23",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-20T19:34:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f8f058a3d8bb0552fbc8c88d9c381c19be326ef6",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): v1.0.22",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-20T19:20:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "57e6bdf5e45bc1b76f31dd29fe529f8ee5eee4ce",
          "body": "- Accept API keys starting with sp_ in addition to sk_ prefix\n- Use dynamic import for eventsource package (ESM compatibility)\n- Pass authorization header via custom fetch function (eventsource v4+ API)",
          "is_bot": false,
          "headline": "fix: support sp_ API key prefix and ESM-compatible eventsource import",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-20T12:04:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4e32808ef41967bf17513df1536872dc5fd57f99",
          "body": "This reverts commit ba6d6aaefc546f57f7913f00e74828fa3f5f5499.",
          "is_bot": false,
          "headline": "Revert \"docs: note backend plan limit env vars in .env.example\"",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-20T00:55:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ba6d6aaefc546f57f7913f00e74828fa3f5f5499",
          "body": null,
          "is_bot": false,
          "headline": "docs: note backend plan limit env vars in .env.example",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-20T00:51:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7af3f9ded8c4e633bc688de050bd7541bfef535c",
          "body": "- Add tag parameter to ListJobsParams type\n- Update docs with tag filter examples",
          "is_bot": false,
          "headline": "feat: add tag filtering support for job listing",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-19T23:43:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "157d8f23b09db220891cf32168da5a87122f9c87",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): v1.0.21",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-19T01:26:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5bb90a83bfd28008883c7ea28cc11b36a7f9acc5",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): v1.0.20",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-18T23:45:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "136427864421c1907097856cdda6bdaa3aa1f38c",
          "body": null,
          "is_bot": false,
          "headline": "chore: remove hardcoded keys from tests/scripts",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-18T23:39:19Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "62cc334fbeaae3c72db3940761e517b96668fbc9",
          "body": null,
          "is_bot": false,
          "headline": "docs: link to backend real-world examples",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-18T22:35:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "80c19082ae9c38884616f4639f727f2db613e3ea",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): v1.0.19",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-18T10:59:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6bd430245fad5e6f8d4f7ecbdfe9365401ade055",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): v1.0.15",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-17T23:00:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5afa4b13615ea30c1d387141335b362b42c22a1b",
          "body": "Cloudflare Tunnel requires HTTPS for HTTP/2 (gRPC).\nRemoved incorrect plaintext HTTP option.",
          "is_bot": false,
          "headline": "docs: fix Cloudflare Tunnel docs - HTTP/2 requires HTTPS",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-17T22:45:31Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "867e1211d0cefc1f36dbbbce220539fe81d68bd8",
          "body": "- Add optimized configuration (disable internal TLS)\n- Clarify legacy vs optimized setup options",
          "is_bot": false,
          "headline": "docs: update gRPC guide with Cloudflare Tunnel optimization",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-17T22:40:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d941cba1a3e7e7ca5d985cd29562a7a132514189",
          "body": null,
          "is_bot": false,
          "headline": "docs: update README with optimized gRPC configuration example",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-17T22:33:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c7459dd6004142dba731709020e221673b39814d",
          "body": null,
          "is_bot": false,
          "headline": "fix: update test scripts",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-17T22:19:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3d2e7f624bd5ab4e1cd8ceef2f69243a614a7545",
          "body": null,
          "is_bot": false,
          "headline": "fix: upgrade local tests",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-17T20:44:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1c9f193dd8411d7ba187ab72e3ee0023973b888c",
          "body": "Test script now uses TLS for production (port 443 or grpc.spooled domain)\nand insecure for localhost/127.0.0.1",
          "is_bot": false,
          "headline": "fix: auto-detect gRPC TLS based on address",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-17T12:20:15Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2c51fcb395280e6b2b21552cc3af8eb46f239357",
          "body": "…-resource\n\n- Add getWebhookToken(), regenerateWebhookToken(), clearWebhookToken() to OrganizationsResource\n- Add WebhookTokenResponse type\n- Expand WorkflowJobOperations with list(), get(), getStatus() methods\n- Add WorkflowJob and WorkflowJobStatus types\n- Add integration tests for webhook token and workflow jobs features\n- Bump version to 1.0.17",
          "is_bot": false,
          "headline": "feat: add organization webhook token management and workflow jobs sub…",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-17T05:09:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "17837f0f080a13a78edc080592e9da2d70410d39",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): v1.0.16",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-17T03:22:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7fc0df598f092f91186f0cbfc024efd2e277f756",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): v0.1.15",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-17T01:07:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "89ae5b7ff7e8140b3d9b5bef085f33e265bd9388",
          "body": "- Document how to enable TLS on self-hosted gRPC with Cloudflare Tunnel\n- Add Cloudflare Tunnel configuration steps\n- Document how to disable TLS for local development",
          "is_bot": false,
          "headline": "docs: Add gRPC TLS configuration for Cloudflare Tunnel",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-16T15:40:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "687a636552ae3244f21ee40b63b8e4b5d8e112a5",
          "body": null,
          "is_bot": false,
          "headline": "fix: remove import.meta usage from test-production.ts",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-16T13:55:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "57a36654c444f025c020ec208790dc5b42ecfe9a",
          "body": "- Add scripts/test-production.ts wrapper for running test-local.ts against\n  production (api.spooled.cloud)\n- Skips stress tests by default to avoid noisy production runs\n- Supports --full flag to enable all tests\n- Add SKIP_STRESS option to test-local.ts for fine-grained control",
          "is_bot": false,
          "headline": "feat: add production test runner script",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-16T13:44:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e21118e88cbb76a2d060ca0dfd864e95682359d6",
          "body": "- Update gRPC client example to use :443\n- Fix unit test cloud address to :443\n- Document GRPC_ADDRESS usage for local vs cloud",
          "is_bot": false,
          "headline": "docs: standardize Spooled Cloud gRPC endpoint to grpc.spooled.cloud:443",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-16T13:07:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "97e8cff03e34c84c644a2f1ee3f723d8f855ef43",
          "body": "- Add cleanupOldJobs() before gRPC, worker, webhook, and edge case tests\n- Reduce job counts in stress tests to fit free tier limits (10 jobs)\n- Add cleanup after job creation tests\n- Fix tier limit tests to use JWT instead of raw API key",
          "is_bot": false,
          "headline": "fix: add job cleanup to tests for free tier compatibility",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-16T12:20:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c21356179ff222b27cb567b3530f247f19e23e93",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): v1.0.14",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-16T05:41:54Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7dfe1e9415b396355ff8333d17cf7033353a34ab",
          "body": "Add client.workflows.retry(id) to retry failed workflows:\n- Resets all failed/deadletter jobs back to pending\n- Clears retry counts and error messages\n- Updates workflow status from failed to running\n\nUpdates:\n- SDK workflows resource with retry method\n- API_CONTRACT.md with new endpoint\n- resources.md and workflows.md docs\n- Unit tests for retry\n- Integration tests for retry",
          "is_bot": false,
          "headline": "feat: add workflow retry method",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-16T05:40:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "912112ff4275335aab590397ce08add4747486b4",
          "body": "- Fix JobHandler return type by casting payload.step to String\n- Add explicit type assertions for worker and grpcClient cleanup\n- Use Number() for stats.total comparison\n- Add missing queueName to updateConfig params\n- Use planTier instead of plan for BillingStatus\n- Replace worker.isRunning with worker.getState()\n- Add explicit array type annotations for Promise.all",
          "is_bot": false,
          "headline": "fix: resolve TypeScript errors in test-local.ts",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-16T05:20:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "320302ff949f15f64e29424943fb73ac41c83b46",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): v1.0.13",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-16T05:12:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "070171eac8ba676063918e18ca8439900ef0174d",
          "body": "Updated docs:\n- getting-started.md: Add plan limits, DLQ, webhooks, organization management sections\n- grpc.md: Add performance metrics (~28x speedup), plan limit enforcement\n- resources.md: Add new methods (webhooks.retryDelivery, auth methods, org methods)\n\nNew sections:\n- Plan Limits table with e\n[…]\nLetter Queue operations (list, retry, purge)\n- Webhooks (retryDelivery)\n- Authentication (startEmailLogin, checkEmail, login, refresh, validate)\n\nAll documentation now reflects current implementation.",
          "is_bot": false,
          "headline": "docs: update SDK documentation with new features and improvements",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-16T04:44:33Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "70f3889493d3d59666d103adfad55a4a23bfac19",
          "body": "- Add Organization Management section (getUsage, generateSlug, checkSlug)\n- Add Webhooks section (create, retryDelivery, getDeliveries)\n- Add Dead Letter Queue operations (list, retry, purge)\n- Add API Key Management section\n- Add Billing & Subscriptions section\n- Add Authentication section (email l\n[…]\needup)\n- Add LimitExceededError to error handling examples\n- Document limit enforcement across all endpoints (HTTP, gRPC, workflows, schedules, DLQ)\n\nAll features reflect current implementation state.",
          "is_bot": false,
          "headline": "docs: update README with new SDK features and performance improvements",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-16T04:37:41Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "38ab2477c1d87d6f2155d7ad1a0a4cf47d347cd9",
          "body": "- Major expansion of test-local.ts with comprehensive endpoint coverage\n- Add missing auth resource methods\n- Add organization resource methods\n- Add webhook resource methods",
          "is_bot": false,
          "headline": "feat: expand test suite and add missing resource methods",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-16T04:18:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fb2bc70a806a1e780907ba72c512264f9a03bf7f",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): v1.0.12",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-16T00:21:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "811861452cc1a8df06bd0958def08079c30849dc",
          "body": null,
          "is_bot": false,
          "headline": "test: add comprehensive local test suite and bootstrap script",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-16T00:03:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "504138553c89acbbfbe88722d75b48826510a659",
          "body": "…agement, admin, email)\n\n- Add metrics endpoint test (port 9090)\n- Add WebSocket connectivity test\n- Add organization management tests (check-slug, generate-slug, list)\n- Add admin endpoints tests (skipped without ADMIN_KEY)\n- Add email login flow tests\n- Fix SDK type issues (statusCode, array returns)\n- Total: 114 tests covering all HTTP API endpoints except gRPC",
          "is_bot": false,
          "headline": "feat(test): add remaining endpoint tests (metrics, websocket, org man…",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-15T20:37:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1423d1ceb6c9ee459ae82ca1ada49023b83e9945",
          "body": "- Add test-local.ts with 106 tests covering all major API endpoints\n- Tests: health, dashboard, org, API keys, jobs (CRUD/bulk/lifecycle/DLQ)\n- Tests: queues, workers, webhooks, schedules, workflows\n- Tests: billing, authentication, registration, worker integration\n- Tests: edge cases, error handling, webhook E2E delivery\n- Add verify-production.ts for interactive production verification\n- gRPC tests skipped by default (server binding issue)",
          "is_bot": false,
          "headline": "feat(test): comprehensive test suite covering 105+ API endpoints",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-15T20:32:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2cca647102cc0a9a5252cb2fad968824ef2a718c",
          "body": "Tests all API endpoints and SDK features:\n- Health, Dashboard, Organizations, API Keys\n- Jobs: CRUD, bulk, lifecycle, failure/retry, DLQ\n- Queues: list, pause/resume\n- Workers: register, heartbeat, deregister\n- Webhooks: CRUD, test, delivery\n- Schedules: CRUD, pause/resume, trigger, history\n- Workflows: dependencies, cancel\n- Authentication: login, validate, refresh, logout\n- SpooledWorker integration\n- Edge cases and error handling\n\nUsage: API_KEY=sk_test_... npx tsx scripts/test-local.ts",
          "is_bot": false,
          "headline": "feat: add comprehensive test suite (87 tests)",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-15T18:40:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9e50e03727125b7c43e11450a2dd9eec0406a9a7",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): v1.0.11",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-15T14:37:48Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "49c9fdd0f8b32247fd18a02bdf437658d82ec2a7",
          "body": "- Add wsUrl config option for explicit WebSocket URL (defaults to derived from baseUrl)\n- Update RealtimeConnectionOptions to support both baseUrl (SSE) and wsUrl (WebSocket)\n- Add comprehensive self-hosted configuration section in docs\n- Update configuration.md with all endpoint options and URL derivation table\n- Update grpc.md with self-hosted gRPC examples\n- Update API_CONTRACT.md with base URL reference table\n- Update README.md with self-hosted hint in quick start example",
          "is_bot": false,
          "headline": "feat: add custom endpoint support for self-hosted deployments",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-15T14:28:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7269c1d1efe684ed2c8c01347095bde6938fe921",
          "body": null,
          "is_bot": false,
          "headline": "docs: update API_CONTRACT.md with webhook token management endpoints",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-15T13:29:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7e55296c275d29e27e2e5fb1317cbc9ff35b7b82",
          "body": null,
          "is_bot": false,
          "headline": "docs: add webhook configuration examples to API_CONTRACT.md",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-15T13:21:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d80de9c38183fd7c577b588cb651b0c7d31c42c1",
          "body": "…ook endpoints\n\n- Removed references to GitHub and Stripe webhook endpoints\n- Added note that custom webhooks provide flexible alternative\n- Documented billing webhook for subscription events",
          "is_bot": false,
          "headline": "docs: update API_CONTRACT.md to reflect removal of GitHub/Stripe webh…",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-15T13:19:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b3d2f7f23854bb8a8c03f14d8043a779228490ee",
          "body": "- Add docs/getting-started.md - installation and first steps\n- Add docs/configuration.md - all config options\n- Add docs/workers.md - SpooledWorker deep dive\n- Add docs/workflows.md - DAG and workflow patterns\n- Add docs/grpc.md - high-performance gRPC guide\n- Add docs/resources.md - complete API re\n[…]\nexamples/workflow-dag.ts - complex workflow example\n- Add examples/grpc-streaming.ts - gRPC streaming example\n- Update README.md with documentation links and cleaner structure\n- Bump version to 1.0.10",
          "is_bot": false,
          "headline": "docs: add comprehensive documentation and examples",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-15T03:46:40Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "9502a709b4b8da7ab06a35e0e65c856ee823c1f6",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): v1.0.9 - fix repo URL case for provenance validation",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-15T03:24:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3d7910b102fce2b6b87789d7c36f419c314732da",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): v1.0.8",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-15T03:21:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "46132d5ac5b923b88d324dcccf727955501c8b05",
          "body": "…est for OIDC)",
          "is_bot": false,
          "headline": "ci(publish): revert to standard setup-node registry-url config (clean…",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-15T03:20:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e2c5eda97f1d4bfa8b84c8d789bae7e59b3d4dcb",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): v1.0.7",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-15T03:16:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fe3aeb5e050f37b82cc6f6d28e1c224f29b73bc2",
          "body": "…Token to trigger OIDC",
          "is_bot": false,
          "headline": "ci(publish): fix ENEEDAUTH - configure .npmrc in home with empty auth…",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-15T03:15:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "231fe81e2c6fae1091363c0ca03f05a57c3104e6",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): v1.0.6",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-15T03:13:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b2ec0ea6d70cecd2c6f0153f7a2624d7e94b14d2",
          "body": "…y auth injection",
          "is_bot": false,
          "headline": "ci(publish): fix E404 - remove setup-node registry-url to avoid legac…",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-15T03:12:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f3009da5a5c2303db8b9659358ab9e26fe0a5664",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): v1.0.5",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-15T03:09:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "960f33d01c9c98229214948c3956b1daae06970e",
          "body": "…pm >= 11.5.1)",
          "is_bot": false,
          "headline": "ci(publish): upgrade npm to latest for Trusted Publishing (requires n…",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-15T03:08:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1ffd76dedc90451450fcfc01bf74f6a986af14f8",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): v1.0.4",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-15T03:04:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1dee10007b4162771990702759cc7387f5ce372a",
          "body": null,
          "is_bot": false,
          "headline": "ci(publish): fix OIDC auth - remove token placeholder from .npmrc",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-15T03:03:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "029ba3ddaa7a0e814d0ee5b64ca12e23418e90a2",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): v1.0.3",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-15T02:59:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2e982262294ee4329c43cbbce94cbab6e816f385",
          "body": null,
          "is_bot": false,
          "headline": "ci(publish): avoid setup-node npmrc token config; rely on OIDC",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-15T02:57:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a552eabde922b9e50a6d227f76720ee7d1ef6900",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): v1.0.2",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-15T02:51:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0a7cc66535ba629da727b05ab2cb72868823de30",
          "body": null,
          "is_bot": false,
          "headline": "ci: fix publish workflow yaml parsing",
          "author_name": "Yevhen Salitrynskyi",
          "author_login": "ysalitrynskyi",
          "committed_at": "2025-12-15T02:47:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        }
      ],
      "releases_count": 3,
      "commits_last_year": 110,
      "latest_release_at": "2026-07-19T14:47:54Z",
      "latest_release_tag": "v1.0.40",
      "releases_from_tags": false,
      "days_since_last_push": 5,
      "active_weeks_last_year": 8,
      "days_since_latest_release": 5,
      "mean_days_between_releases": 3
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": false,
      "health_percentage": 50,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": [
        {
          "name": "@spooled/sdk",
          "exists": true,
          "license": "Apache-2.0",
          "keywords": [
            "spooled",
            "job-queue",
            "task-queue",
            "background-jobs",
            "webhooks",
            "cron",
            "scheduler",
            "workflow"
          ],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/@spooled/sdk",
          "is_deprecated": false,
          "latest_version": "1.0.40",
          "repository_url": "https://github.com/Spooled-Cloud/spooled-sdk-nodejs",
          "versions_count": 30,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 1,
          "monthly_downloads": 2076,
          "first_published_at": "2025-12-15T02:41:00.638000Z",
          "latest_published_at": "2026-07-19T14:48:12.294000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 5
        }
      ]
    },
    "popularity": {
      "forks": 0,
      "stars": 5,
      "watchers": 0,
      "fork_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_forks": 0
      },
      "star_history": null,
      "open_issues_and_prs": 0
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [
        "examples"
      ],
      "has_llms_txt": false,
      "has_dockerfile": false,
      "has_mcp_signal": false,
      "bootstrap_files": [],
      "api_schema_files": [
        "proto/spooled.proto"
      ],
      "has_devcontainer": false,
      "typecheck_configs": [
        "tsconfig.json"
      ],
      "toolchain_manifests": [],
      "largest_source_bytes": 137922,
      "source_files_sampled": 96,
      "oversized_source_files": 1,
      "agent_instruction_files": [
        ".cursor/rules/kb-sync.mdc",
        "AGENTS.md"
      ],
      "agent_instruction_max_bytes": 502
    },
    "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": 36,
        "malicious_count": 0,
        "assessed_package": "npm:@spooled/sdk@1.0.40",
        "unassessed_count": 0,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "npm"
      ],
      "dependencies": [
        {
          "name": "@grpc/grpc-js",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.14.3"
        },
        {
          "name": "@grpc/proto-loader",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.8.0"
        },
        {
          "name": "eventsource",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "^3.0.7"
        },
        {
          "name": "ws",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "^8.20.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": 0,
        "open_issues": 0,
        "closed_ratio": null,
        "closed_issues": 0,
        "closed_unmerged_prs": 0
      },
      "bus_factor": 1,
      "bot_contributors": 0,
      "top_contributors": [
        {
          "type": "User",
          "login": "ysalitrynskyi",
          "commits": 110,
          "avatar_url": "https://avatars.githubusercontent.com/u/25203302?v=4"
        }
      ],
      "contributors_sampled": 1,
      "top_contributor_share": 1
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "publish.yml"
      ],
      "has_docs_dir": true,
      "linter_configs": [
        "eslint.config.js"
      ],
      "has_editorconfig": false,
      "has_linter_config": true,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [
        "package-lock.json"
      ],
      "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": 3,
            "reason": "branch protection is not maximal on development and all release branches",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": null,
            "reason": "no pull request found",
            "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/30 approved changesets -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 6,
            "reason": "project has 2 contributing companies or organizations -- score normalized to 6",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": 10,
            "reason": "no dangerous workflow patterns detected",
            "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": 10,
            "reason": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
          },
          {
            "name": "Packaging",
            "score": 10,
            "reason": "packaging workflow detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": 2,
            "reason": "dependency not pinned by hash detected -- score normalized to 2",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "no SAST tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 0,
            "reason": "security policy file not 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": 10,
            "reason": "GitHub workflow tokens follow principle of least privilege",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 7,
            "reason": "3 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "06d0f5ddad724239cef7b8b598fb0fbaa45779c0",
        "ran_at": "2026-07-25T12:41:44Z",
        "aggregate_score": 5.3,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": false,
      "has_dependabot_config": false
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-19T14:48:17Z",
      "oldest_open_prs": [],
      "last_merged_pr_at": null,
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": []
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/Spooled-Cloud/spooled-sdk-nodejs",
    "host": "github.com",
    "name": "spooled-sdk-nodejs",
    "owner": "Spooled-Cloud"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 60,
      "inputs": {
        "security": 62,
        "vitality": 82,
        "community": 35,
        "governance": 36,
        "engineering": 88
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "good",
        "name": "Vitality",
        "value": 82,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "good",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 70,
            "inputs": {
              "commits_last_year": 110,
              "human_commit_share": 1,
              "days_since_last_push": 5,
              "active_weeks_last_year": 8
            },
            "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": "8/52 weeks with commits",
                "points": 5.5,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 8
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "110 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 110
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
                "points": 10,
                "status": "met",
                "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": 3,
              "latest_release_tag": "v1.0.40",
              "releases_from_tags": false,
              "days_since_latest_release": 5,
              "mean_days_between_releases": 3
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "3 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 3
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 5 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 5
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~3 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 3
                    }
                  }
                ],
                "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": "maintained",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": null,
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": 5,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "last human commit 5 days ago",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_maintained",
                    "params": {
                      "days": 5
                    }
                  }
                ],
                "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": 10,
            "inputs": {
              "forks": 0,
              "stars": 5,
              "watchers": 0,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "5 stars",
                "points": 9.8,
                "status": "partial",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 5
                    }
                  }
                ],
                "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 (Apache-2.0)",
                "points": 22.5,
                "status": "met",
                "details": [
                  {
                    "code": "license_standard",
                    "params": {}
                  },
                  {
                    "code": "license_spdx",
                    "params": {
                      "spdx": "Apache-2.0"
                    }
                  }
                ],
                "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": 55,
            "inputs": {
              "packages": [
                "@spooled/sdk"
              ],
              "dependents": null,
              "ecosystems": "npm",
              "total_downloads": null,
              "monthly_downloads": 2076
            },
            "components": [
              {
                "key": "monthly_downloads",
                "name": "Monthly downloads",
                "detail": "2,076 downloads/month across npm",
                "points": 44.2,
                "status": "partial",
                "details": [
                  {
                    "code": "downloads_monthly",
                    "params": {
                      "count": 2076,
                      "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": "at_risk",
        "name": "Sustainability & Governance",
        "value": 36,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "critical",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 16,
            "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 2 contributing companies or organizations -- score normalized to 6",
                "points": 6,
                "status": "partial",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "critical",
            "name": "Issue & PR responsiveness",
            "note": "Excluded from scoring (no data or not applicable): Issue resolution, PR acceptance. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "issue_resolution",
                    "pr_acceptance"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 1,
            "inputs": {
              "merged_prs": 0,
              "open_issues": 0,
              "closed_issues": 0,
              "issue_closed_ratio": null,
              "closed_unmerged_prs": 0
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "no issues or no data",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_issues_or_data",
                    "params": {}
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "no decided pull requests or no data",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_decided_prs_or_data",
                    "params": {}
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 0/30 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": 42,
            "inputs": {
              "followers": 3,
              "owner_type": "Organization",
              "is_verified": null,
              "owner_login": "Spooled-Cloud",
              "public_repos": 8,
              "account_age_days": 228
            },
            "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": "3 followers of Spooled-Cloud",
                "points": 4.3,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 3,
                      "login": "Spooled-Cloud"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "8 public repos, account ~0 yr old",
                "points": 8.2,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 8
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 0
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "@spooled/sdk"
              ],
              "ecosystems": "npm",
              "any_deprecated": false,
              "min_days_since_publish": 5
            },
            "components": [
              {
                "key": "published_resolvable",
                "name": "Published & resolvable",
                "detail": "1 package(s) on npm",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "packages_published",
                    "params": {
                      "count": 1,
                      "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": "30 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 30
                    }
                  }
                ],
                "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": "excellent",
        "name": "Engineering Quality",
        "value": 88,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "good",
            "name": "Engineering practices",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: CI-Tests. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_ci_tests"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 80,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": true,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "1 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "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",
                "points": 16,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "eslint.config.js"
                    }
                  }
                ],
                "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": "no pull request found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "excellent",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "topics": [
                "async",
                "client-library",
                "javascript",
                "nodejs",
                "npm",
                "sdk",
                "type-safe",
                "typescript",
                "webhook"
              ],
              "has_wiki": true,
              "homepage": "https://spooled.cloud",
              "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://spooled.cloud",
                "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": "9 topics",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "topics_count",
                    "params": {
                      "count": 9
                    }
                  }
                ],
                "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": "moderate",
        "name": "Security",
        "value": 62,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "moderate",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): CI-Tests, Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "ci_tests",
                    "signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 53,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 16,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 2,
              "scorecard_aggregate": 5.3
            },
            "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 is not maximal on development and all release branches",
                "points": 2.2,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "no pull request found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "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/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 2 contributing companies or organizations -- score normalized to 6",
                "points": 1.5,
                "status": "partial",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no dangerous workflow patterns detected",
                "points": 10,
                "status": "met",
                "details": [],
                "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": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "packaging",
                "name": "Packaging",
                "detail": "packaging workflow detected",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 2",
                "points": 1,
                "status": "partial",
                "details": [],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "no SAST tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file not detected",
                "points": 0,
                "status": "missed",
                "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": "GitHub workflow tokens follow principle of least privilege",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "3 existing vulnerabilities detected",
                "points": 5.2,
                "status": "partial",
                "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:@spooled/sdk@1.0.40 runtime dependency closure — what installing the published package pulls in — 36 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:@spooled/sdk@1.0.40",
                  "assessed": 36
                }
              },
              {
                "code": "advisories_reachability",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "source": "osv",
              "advisories": 0,
              "affected_packages": 0,
              "assessed_packages": 36,
              "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": 36,
              "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": 3
            },
            "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": "good",
        "name": "AI Readiness",
        "value": 75,
        "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": 0.98,
              "agent_instruction_files": [
                ".cursor/rules/kb-sync.mdc",
                "AGENTS.md"
              ],
              "agent_instruction_max_bytes": 502
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": ".cursor/rules/kb-sync.mdc, AGENTS.md",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": ".cursor/rules/kb-sync.mdc, AGENTS.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": "98 of 100 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 98,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "moderate",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 56,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [
                "package-lock.json"
              ],
              "has_dockerfile": false,
              "typed_language": true,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": true,
              "typecheck_configs": [
                "tsconfig.json"
              ],
              "agent_commit_share": 0,
              "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",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "eslint.config.js"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": "tsconfig.json",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "tsconfig.json"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": "lockfile",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "lockfile"
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "no agent-authored commits among the last 100",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_agent_authored_commits",
                    "params": {
                      "sampled": 100
                    }
                  }
                ],
                "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 2",
                "points": 2,
                "status": "partial",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "excellent",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 99,
            "inputs": {
              "primary_language": "TypeScript",
              "largest_source_bytes": 137922,
              "source_files_sampled": 96,
              "oversized_source_files": 1
            },
            "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": "1/96 source files over 60KB",
                "points": 54.4,
                "status": "partial",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 96,
                      "oversized": 1
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          },
          {
            "key": "ai_interfaces",
            "band": "good",
            "name": "Machine-readable interfaces",
            "note": null,
            "notes": [],
            "value": 80,
            "inputs": {
              "example_dirs": [
                "examples"
              ],
              "has_mcp_signal": false,
              "api_schema_files": [
                "proto/spooled.proto"
              ]
            },
            "components": [
              {
                "key": "api_schema_openapi_graphql_proto",
                "name": "API schema (OpenAPI/GraphQL/proto)",
                "detail": "proto/spooled.proto",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "proto/spooled.proto"
                    }
                  }
                ],
                "max_points": 40
              },
              {
                "key": "mcp_server",
                "name": "MCP server",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              },
              {
                "key": "runnable_examples",
                "name": "Runnable examples",
                "detail": "examples",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "examples"
                    }
                  }
                ],
                "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": [
    "Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token",
    "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-25T12:41:51.168877Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/s/Spooled-Cloud/spooled-sdk-nodejs.svg",
  "full_name": "Spooled-Cloud/spooled-sdk-nodejs",
  "license_state": "standard",
  "license_spdx": "Apache-2.0"
}

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

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

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