JSON-Rohbericht maschinenlesbar
{
"data": {
"repo": {
"topics": [],
"is_fork": false,
"size_kb": 1097,
"has_wiki": false,
"homepage": null,
"languages": {
"Go": 972389,
"TypeScript": 360441
},
"pushed_at": "2026-07-13T13:02:57Z",
"created_at": "2026-05-25T17:20:55Z",
"owner_type": "Organization",
"updated_at": "2026-07-13T13:04:18Z",
"description": "wapps umbrella CLI — age secrets + Coolify shim + git auto-sync",
"is_archived": false,
"is_disabled": false,
"license_spdx": "MIT",
"default_branch": "main",
"license_spdx_raw": "MIT",
"primary_language": "Go",
"significant_languages": [
"Go",
"TypeScript"
]
},
"owner": {
"blog": null,
"name": null,
"type": "Organization",
"login": "wappsdev",
"company": null,
"location": null,
"followers": 2,
"avatar_url": "https://avatars.githubusercontent.com/u/254932202?v=4",
"created_at": "2026-01-14T15:11:17Z",
"is_verified": null,
"public_repos": 3,
"account_age_days": 194
},
"license": {
"state": "standard",
"spdx_id": "MIT",
"raw_spdx": "MIT",
"file_present": true,
"scorecard_found": true,
"profile_has_license": true
},
"activity": {
"releases": [
{
"tag": "v0.19.0",
"kind": "minor",
"published_at": "2026-07-13T12:33:11Z"
},
{
"tag": "v0.18.0",
"kind": "minor",
"published_at": "2026-07-13T10:29:36Z"
},
{
"tag": "v0.17.2",
"kind": "patch",
"published_at": "2026-07-12T00:13:41Z"
},
{
"tag": "v0.17.1",
"kind": "patch",
"published_at": "2026-07-11T23:34:42Z"
},
{
"tag": "v0.17.0",
"kind": "minor",
"published_at": "2026-07-11T23:13:51Z"
},
{
"tag": "v0.16.1",
"kind": "patch",
"published_at": "2026-07-01T11:32:56Z"
},
{
"tag": "v0.16.0",
"kind": "minor",
"published_at": "2026-06-28T20:00:58Z"
},
{
"tag": "v0.15.0",
"kind": "minor",
"published_at": "2026-06-09T15:08:25Z"
},
{
"tag": "v0.14.1",
"kind": "patch",
"published_at": "2026-06-04T21:35:03Z"
},
{
"tag": "v0.14.0",
"kind": "minor",
"published_at": "2026-06-03T20:16:18Z"
},
{
"tag": "v0.13.2",
"kind": "patch",
"published_at": "2026-05-28T21:23:18Z"
},
{
"tag": "v0.13.1",
"kind": "patch",
"published_at": "2026-05-28T20:37:17Z"
},
{
"tag": "v0.13.0",
"kind": "minor",
"published_at": "2026-05-28T18:45:57Z"
},
{
"tag": "v0.12.0",
"kind": "minor",
"published_at": "2026-05-28T14:14:04Z"
},
{
"tag": "v0.11.1",
"kind": "patch",
"published_at": "2026-05-28T04:03:18Z"
},
{
"tag": "v0.11.0",
"kind": "minor",
"published_at": "2026-05-28T03:37:09Z"
},
{
"tag": "v0.5.1",
"kind": "patch",
"published_at": "2026-05-26T00:36:19Z"
},
{
"tag": "v0.5.0",
"kind": "minor",
"published_at": "2026-05-26T00:27:49Z"
},
{
"tag": "v0.4.0",
"kind": "minor",
"published_at": "2026-05-26T00:00:39Z"
},
{
"tag": "v0.3.1",
"kind": "patch",
"published_at": "2026-05-25T22:31:46Z"
},
{
"tag": "v0.3.0",
"kind": "minor",
"published_at": "2026-05-25T22:28:45Z"
},
{
"tag": "v0.2.0",
"kind": "minor",
"published_at": "2026-05-25T19:07:17Z"
},
{
"tag": "v0.1.0",
"kind": "minor",
"published_at": "2026-05-25T18:56:51Z"
}
],
"recent_commits": [
{
"oid": "db07ff7e9202b19860ea58cf411672589d122c8c",
"body": "….19.0+) (#34)",
"is_bot": false,
"headline": "docs(skill): add `wapps tofu` to the embedded wapps-secrets skill (v0…",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-07-13T13:02:57Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "60c8da713e506be162effe84ff37286a648ec501",
"body": "… exec --prefix '' -- tofu` (#33)\n\n`wapps secrets exec --project X --prefix '' -- tofu apply` üç ayrı parça istiyordu\nve kafa karıştırıyordu: `--project` (cwd `.wapps.yaml`'dan zaten çözülür), `--prefix ''`\n(gerekli ama tuzak — store anahtarları tam isimle durur, TF_VAR_ default'u çift-prefix\nyapard\n[…]\nthrough verbatim, verbatim-prefix (çift-prefix yok), scrub,\n store+legacy backend, F1 regresyon (UnpinnedRefused: exfiltration bloke + service-token\n exempt + legacy no-op). go build/vet/test yeşil.",
"is_bot": false,
"headline": "feat(cli): add `wapps tofu` — clean first-class wrapper over `secrets…",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-07-13T12:31:55Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "2da78e23260b09b940527b3a93f7bf8cdd327c1f",
"body": "…dr bootstrap + epoch-reset, mTLS, worker replication (#32)\n\n* feat(worker): audit-head route, per-key alert-on-read, state replication + SchedulerDO\n\nZero-git store hedef mimarisinin (docs/wapps-secrets-zero-git-architecture.md)\nWorker tarafı — Faz 2 + P1.4/P1.11:\n\n- GET /v1/audit/head: AuditLogDO'\n[…]\np); tofu.BootstrapEnvVars kataloğu (preflight superset invariant'ı).\n\nTF_VAR_state_passphrase kontratı (backend.tf encryption bloğu var.state_passphrase\nokur) — F3 recovery TF_ENCRYPTION inline değil.",
"is_bot": false,
"headline": "feat(secrets): zero-git store core — deploy/dr/coolify store-backed, …",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-07-13T09:57:53Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "af19fe566660a021b1e9cdf49cc2d5e702a1df13",
"body": "…ody (#31)\n\n* feat(secrets): dr split / dr combine — MASTER_KEK Shamir offline custody\n\nThe server-decrypt store's only root secret is the MASTER_KEK (a live wrangler Worker\nsecret). There was a way to RESTORE from Shamir shares (dr restore) but no way to\nCREATE them. Add:\n- 'wapps dr split' — takes\n[…]\ny + shares (parity with split) and warns\nthat the printed kid MUST be compared before use (too few/mismatched shares yield a\nsilently-wrong key). --master-hex help notes the ps/shell-history exposure.",
"is_bot": false,
"headline": "feat(secrets): dr split / dr combine — MASTER_KEK Shamir offline cust…",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-07-12T00:12:37Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "381161f3877b656aaa98f3ce9a3f10efdb91f0b5",
"body": "…backend (#30)\n\nThe embedded agent skill only described the legacy git-age archive. Add store-backend\nawareness (both backends, same apply-only commands; wapps login for the store; auth-\nerror → login vs passphrase) so agents don't suggest passphrase/sync flows on migrated\nprojects. Apply-only safety rule + what-not-to-do unchanged. Asset + .claude copy synced.",
"is_bot": false,
"headline": "docs(skill): update wapps-secrets skill for the server-decrypt store …",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-07-11T23:33:40Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "8a48942c37da9495ae98fad81b55ccb4cdaea247",
"body": "…dedWallTime) (#29)\n\n* fix(secrets): parallelize writer-DO blob writes (bulk import exceededWallTime)\n\nA 156-key migration import 500'd (error 1101, exceededWallTime) because the writer\nDO wrote blobs SEQUENTIALLY — 156 awaited HEAD+PUT round-trips (~312 serial R2 ops)\nblew the DO wall-time budget. \n[…]\novery text (not re-auth)\n\ncodex P3: NOT_AVAILABLE's registry recovery is about needing a live CF Access session,\nwhich misleads on an oversized read. WithRecovery overrides it to 'request fewer keys'.",
"is_bot": false,
"headline": "fix(secrets): parallelize bulk write/read R2 fan-out (migration excee…",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-07-11T21:38:30Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "d352a4a6f5e880ddbfdd88ce2e0583e2bc0a6237",
"body": "… fold case (#28)\n\n* fix(secrets): accept POSIX env-var key names (mixed case), not upper-only\n\nKEYNAME_RE was /^[A-Z][A-Z0-9_]{0,127}$/ (upper-only), which rejected the real\ninfra secrets the store must hold: tofu vars whose names are CONTRACTUAL\n(TF_VAR_cloudflare_api_token → var.cloudflare_api_to\n[…]\ned POSIX-env-var KEYNAME_RE, __proto__\nrejection, deny-side folding (enforcement + linter canMatchProd/deniedByRule).\nTests updated: allow case-sensitive, deny case-insensitive, mixed-case round-trip.",
"is_bot": false,
"headline": "fix(secrets): accept POSIX env-var key names (mixed case); deny globs…",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-07-11T20:05:29Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "6b0e0ea55b56e6113c6c85da0ec5cacedb7a8da2",
"body": "…t callback) (#27)\n\n* fix(secrets): wapps login via cloudflared (CF Access rejects localhost callback)\n\nThe CF Access CLI flow does not support a localhost-callback redirect_url — it\nreturns 'Invalid redirect URL'. The only supported browser flow is edge token\ntransfer (redirect to the app's own dom\n[…]\ne generic live-session advice. Add cloudflared\nto runDoctorFull's dependency scan and override the error Recovery with a platform-\nneutral install instruction so operators get an actionable next step.",
"is_bot": false,
"headline": "fix(secrets): wapps login via cloudflared (CF Access rejects localhos…",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-07-11T18:36:53Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "759133a25c2179d3feff175926ca64567c1fd725",
"body": "…n't advertise the store) (#26)\n\nThe secret-store hostname openly advertised its function (recon signal). Renamed to a neutral\ngw.meapps.dev / gw-staging.meapps.dev (defense-in-depth; the real controls stay CF Access + crypto).\nCLI DefaultGateURL, wrangler custom_domain routes, comments + tests updated. Access app AUDs unchanged\n(per-app). Live CF change already applied (Access app domains + worker custom domains re-pointed;\nold secrets.* removed). Bucket names (wapps-secrets-*) unchanged.",
"is_bot": false,
"headline": "chore(secrets): rename gate hostname secrets→gw.meapps.dev (opsec: do…",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-07-11T17:38:48Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "d2d171d6480594270ebf2991f8d390ad5ed24fd4",
"body": "…deploy (#25)\n\nProd Worker (secrets-gate) deployed live: real prod bindings (wapps-secrets-prod R2, audit_prod D1\nf33848e6, jti/rate/IDENTITY_CACHE_prod KV), ACCESS_AUD_READ/WRITE, ADMIN_EMAILS=adnan@wapps.co,\nteam domain wapps-dev.cloudflareaccess.com, custom_domain secrets.meapps.dev, crons remove\n[…]\nped to R2 (developers→all read/write, admins→*, infra→+rotate). secrets.meapps.dev\nis CF-Access-gated (302 → Google SSO). Deployed via wrangler + workers/domains API (token lacks Workers Routes:Edit).",
"is_bot": false,
"headline": "chore(secrets): wire prod wrangler.jsonc for the live server-decrypt …",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-07-11T17:29:04Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "2a519abeb0d14de1d447d9252ec35ea21b18a893",
"body": "…oup-gated store (#24)\n\n* feat(secrets): server-decrypt Worker core — CF-Access + Google-group gated (pivot from zero-knowledge)\n\nPivots the Worker from zero-knowledge (per-key X25519 wraps + M-of-N roster) to server-side decryption\ngated by CF Access + Google Workspace groups, per the SPEC-READY sp\n[…]\npath):\nexport completeness proof still trusts IsRootAdmin (root reads are also policy-filtered) + import --confirm can\nbe bypassed for write-only-readable keys. To harden before the real prod cutover.",
"is_bot": false,
"headline": "feat(secrets): server-decrypt pivot — CF Access + Google Workspace gr…",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-07-11T17:13:22Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "e937aca9af63b8658ffc44faeb7839f294cab9b0",
"body": "…ging deploy config (#23)\n\nCF Workers Free plan rejects new_classes (KV-backed) DOs with code 10097 (\"must use\nnew_sqlite_classes\"). SQLite-backed DOs are the modern default and expose the same state.storage\nAPI (no DO code change), so the migration is a safe, cost-avoiding switch for fresh (never-d\n[…]\nuts (D1/KV/R2 ids, staging\nREAD AUD, team domain) — secrets-gate-staging deployed successfully to workers.dev and fails closed\n(503) pending GENESIS_TRUST_SHA256 + MINT_KEY (set at the root ceremony).",
"is_bot": false,
"headline": "fix(worker): SQLite-backed Durable Objects (Free-tier eligible) + sta…",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-07-11T02:05:43Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "1089def1856205e059e97957ccf9c0d64871e662",
"body": "…w rounds 1-11) (#22)\n\nPR #21 was squash-merged from a stale branch that predated the codex GPT-5.6 adversarial review\nloop; this lands the full codex-CLEAN hardening (50 files) that was missing from main:\n\n- Go<->TS strict-shape consensus gate + 103-vector cross-language parity oracle (Go verdict =\n[…]\n verdict: CLEAN (round 12). Verified: go build+vet+gofmt clean, go test ./... 28 pkgs ok;\nworker tsc clean, npm test 20 files / 312 tests pass. Tree is identical to the verified tag secrets-codex-r11.",
"is_bot": false,
"headline": "fix(secrets): codex-clean consensus + offboard authz hardening (revie…",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-07-11T00:57:12Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "70adab1384c1b81e539a4274a420e84a324bf238",
"body": "…) (#21)\n\n* feat(secrets): crypto core — cryptoid + manifest (G2)\n\ninternal/cryptoid: X25519 encryption identities (+ plugin recipient parsing +\noffline fingerprints), separate Ed25519/ECDSA-P256 detached signing over exact\nbytes (verify-before-parse), per-key DEK envelope (XChaCha20-Poly1305, bucke\n[…]\n); set->get round-trip; enroll reload/sign proof.\n\nGo build + touched-pkg tests green; the real login remains the only account-gated step.\n(pre-existing gofmt/lint debt in untouched files left alone.)",
"is_bot": false,
"headline": "feat(secrets): git-free Cloudflare-native secret store (wapps-secrets…",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-07-11T00:50:48Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "49a3f2fa0b27122f6cb761d16ed5f32f416aa592",
"body": "wapps secrets exec/env prepended the .wapps.yaml source prefix (default\nTF_VAR_) to every archive key unconditionally. A key stored already-prefixed\n(e.g. TF_VAR_gemini_api_key, set directly into the archive rather than derived\nfrom a Tofu output) became TF_VAR_TF_VAR_gemini_api_key and never reache\n[…]\n(env,\nall three value branches). find-bugs clean.\n\nTests: TestEnvName_Idempotent + TestBuildExecEnv_IdempotentPrefix (mixed\narchive: bare key gains prefix, already-prefixed stays verbatim, no double).",
"is_bot": false,
"headline": "fix(secrets): idempotent env prefix in exec/env (no double TF_VAR_)",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-07-01T11:31:55Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "b86ef3c5dd2f801a97b01a8c90ea889f02409a9b",
"body": null,
"is_bot": false,
"headline": "docs(changelog): cut v0.16.0",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-06-28T19:59:54Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "d6b665c901b06d4881ab22acda3dd686db1296ac",
"body": "Implements deploy-tooling-gaps P1 + P4 to the full wapps-deploy-spec,\nvalidated against the proxy server's deploy-proxy/main.go (source of truth).\nGives every non-CI deploy (manual ops, break-glass, an AI agent) a supported\npath instead of hand-reconstructing the pipeline's inline curl + gathering\nc\n[…]\n (env-beats-archive, legacy-fallback, missing-cred,\nunknown-repo, bad-name, e2e trigger, out-of-scope no-poll, migrator --wait,\n--wait+--json single-object, --wait failed single-line, AI-safe golden).",
"is_bot": false,
"headline": "feat(deploy): wapps deploy <service> via company-deploy-proxy",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-06-28T19:59:31Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "8f29ab711dfb7255fbbf43b9f9a4cd75d39060b7",
"body": null,
"is_bot": false,
"headline": "docs(changelog): cut v0.15.0",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-06-09T15:07:13Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "77b1fbe0695c1151400886a488262f007432c3f4",
"body": null,
"is_bot": false,
"headline": "docs(changelog): wapps skill install",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-06-09T15:06:50Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "23929758c1a7dd90515460d02e4dd65c6304ca61",
"body": "…skill\n\nShips the AI-safe wapps-secrets Claude Code skill INSIDE the binary\n(//go:embed) so a Homebrew install — which has no repo checkout — can\ninstall it with no source tree:\n\n wapps skill install user-wide ~/.claude/skills (default)\n wapps skill install --local --copy committa\n[…]\ntmp with a fake HOME;\nreal-dir + file-symlink layout confirmed; status/refresh round-trip green.\n9 tests in internal/skill; find-bugs pass (fixed the flag-before-subcommand\nauto-refresh double-print).",
"is_bot": false,
"headline": "feat(skill): wapps skill install — embed + install the wapps-secrets …",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-06-09T15:06:50Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "56d6e7b599057c4c3e8f4cf052c2da49b9a287db",
"body": null,
"is_bot": false,
"headline": "docs(changelog): cut v0.14.1",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-06-04T21:33:54Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "16da2e7dde291bd97532c214c8a823b192346e45",
"body": "readKey unmarshaled the entire archive into a map[string]struct{Value string}\nand failed the moment ANY key held a non-string value (e.g. the array\nvaulter_traefik_cert_paths) — crashing 'wapps secrets get <key>' before it\never reached the requested (string) key. import-env'd secrets were thus\nvisib\n[…]\non a string key with an array key present (the crash\nrepro), get on an array key (compact JSON), rawValueToString edge cases\n(null/absent/array/number/bool/object), exec inclusion with/without prefix.",
"is_bot": false,
"headline": "fix(get): don't crash on archives containing a non-string value",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-06-04T21:33:33Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "6a7bc6cd360300a86f4ae510f8e975faeaec71c5",
"body": null,
"is_bot": false,
"headline": "docs(changelog): cut v0.14.0",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-06-03T20:14:46Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "10a7d680c600eadd79ad4e67043c6a91c778f9be",
"body": "Standalone before/after explainer + operator runbook for the\n--config/--project / config-dir-relative feature shipping in v0.14.0.\nComplements the architecture.md §3 reference and the onboarding note.",
"is_bot": false,
"headline": "docs: dedicated secrets-from-anywhere before/after guide",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-06-03T20:14:34Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "77cad91f8f2efc4f64ffc82d9f60c8f905f056e8",
"body": "…ented",
"is_bot": false,
"headline": "docs: secrets-from-anywhere (--config/--project) + spec marked implem…",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-06-03T20:14:14Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "80df113b017909ddad6782ad477a635f70e4ba41",
"body": "--project <name> / -p resolves a registered project from\n~/.config/wapps/projects.yaml (name → dir, XDG-aware, ~ expansion) to its\n.wapps.yaml, then feeds the same configRoot path resolution. Mutually\nexclusive with --config (cobra MarkFlagsMutuallyExclusive + a belt check);\n--config gains -c. Unkno\n[…]\nets.SetConfigPath, and runs the git auto-sync preflight against\nconfigRoot (the project repo) instead of cwd, skipping cleanly when that dir\nisn't a git work tree (Fix 3). Covers acceptance #3 and #6.",
"is_bot": false,
"headline": "feat(cli): --project registry + git preflight on configRoot",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-06-03T20:14:14Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "e6b8bdb7aac620292f5701db173ffa697039fb40",
"body": "…ve site\n\nThe --config flag was dead: every secrets command loaded a hardcoded\n'.wapps.yaml' and resolved the archive against cwd. New package seam —\nSetConfigPath/wappsConfigPath()/configPathOverride — lets root hand the\nresolved config path in; config.Load then records configRoot and the Resolve*\n\n[…]\nented, outside the from-anywhere acceptance set).\n- rotate-master's audit log records the raw relative archive path for parity.\n\nconfigroot_test.go covers acceptance #1,#2,#4,#5,#7 from a foreign cwd.",
"is_bot": false,
"headline": "feat(secrets): honor --config/--project via configRoot at every archi…",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-06-03T20:14:14Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "84f80be3a2ea2ee38385653ddd99469f47c77eec",
"body": "Load now records the absolute directory of the loaded .wapps.yaml as an\nunexported configRoot. New helpers resolve relative paths against it:\nResolveDest, Target.ResolvePath, ResolvedSources (file path + tofu workdir),\nand a general Resolve. Absolute paths and Parse-built configs (configRoot\n\"\") pas\n[…]\nurce with an omitted workdir defaults to configRoot (mapped \"\" →\n\".\") so a --project sync never silently runs 'tofu output' in the operator's\ncwd; file sources keep an empty workdir (they reject one).",
"is_bot": false,
"headline": "feat(config): config-dir-relative path resolution",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-06-03T20:14:14Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "6ecf98f2f2033570850f8f021caeb6b712f923a0",
"body": "ADDENDUM 2: Coolify returns the SAME key twice when an env is defined for\nboth runtime and preview deployments — is_preview=false (production runtime)\nand is_preview=true (per-PR preview), with possibly different values. The\nnaive currentByKey build was last-write-wins, so the preview value (observe\n[…]\no-op.\n\nTests: is_preview parse; preview dup → no change (runtime matches);\norder-independence (runtime wins either way); preview-only key → add not\ncompare. find-bugs: 6 semantics verified, no issues.",
"is_bot": false,
"headline": "feat(coolify): ignore is_preview-duplicate envs in the sync diff",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-28T21:21:56Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "7073eacb8ae7213c91c896a7bd4c34196b3b844b",
"body": "v0.13.0 was tagged while its content still sat under [Unreleased].\nReconcile: the multi-app sync, update-check, coverage, and hardening\nsweep are v0.13.0 (already shipped); is_coolify filter + exclude_keys\nare v0.13.1 (this release).",
"is_bot": false,
"headline": "docs(changelog): split v0.13.0 / v0.13.1 sections",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-28T20:36:00Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "bdfe2945da0428bcb78f2d4ca59d4d421ed42680",
"body": "Two diff filters from the multi-app handoff ADDENDUM, so a Coolify sync\nnever fights keys it doesn't own.\n\nis_coolify filter (the high-priority one):\n Coolify generates read-only 'magic' envs (SERVICE_FQDN_*, SERVICE_URL_*)\n flagged is_coolify=true. A PATCH against one 422s; under delete_unmanaged\n[…]\nmanaged Coolify-only key not\nremoved; exclude_keys drops + counts only matched; end-to-end multi-app\nskip-and-report. Docs + CHANGELOG updated.\n\nShips in the next release alongside the multi-app work.",
"is_bot": false,
"headline": "feat(coolify): skip is_coolify-managed envs + coolify_sync.exclude_keys",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-28T20:35:03Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "395b3be57112a272456d4e0ed2c0319d064279d0",
"body": "Canonical 'how the system works' doc covering the data model (sources →\narchive → consumers), the full .wapps.yaml schema, the command surface,\nboth Coolify sync modes, the safety model, what's committed vs gitignored,\nversioning/distribution, and package layout.\n\nComplements the existing task-oriented onboarding.md and chronological\nCHANGELOG.md — this is the reference an engineer reads to understand the\narchitecture before touching it.",
"is_bot": false,
"headline": "docs: architecture & reference for the wapps secret system",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-28T19:43:06Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "eb7e1d231b8fe995b9678e162309cf0509d5d48c",
"body": "A multi-app archive (one .enc.age holding KREEVA_WEB_*, ROYCO_API_*, ...)\ncan now be pushed back to Coolify with each app receiving only its own\nprefix-matched subset, prefix-stripped, non-destructively by default.\n\nNew surface:\n wapps secrets sync --target=coolify --all-apps [--force]\n\n.wapps.yaml\n[…]\nation (overlap both orders, dup, missing fields),\narchiveToAppMap (strip/filter/exact-match-skip), per-app subset isolation,\ndelete_unmanaged on/off, dry-run, zero-match skip, apply-failure isolation.",
"is_bot": false,
"headline": "feat(coolify): multi-app sync via --all-apps + coolify_sync.apps mapping",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-28T18:44:28Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "3c2fe3729681c74a95d8aa5e7e7bf3f91b868724",
"body": "Released binaries now check GitHub's releases-latest endpoint at most once\nper 24h (cached in <user-cache>/wapps/version-check.json) and print a one-\nline upgrade notice on stderr after the command runs.\n\nGating (all intentional):\n - Only semver-tagged release binaries check. Local builds (Version \n[…]\nd: documents the behavior + opt-out under Step 1.\n\n15 new tests covering semver parse/compare, cache freshness + refetch,\natomic cache write, all error swallow paths, and the escape-injection\ndefense.",
"is_bot": false,
"headline": "feat(updatecheck): daily best-effort 'newer release available' notice",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-28T18:02:56Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "2978d5237cf481f021e090638484cb639eb8377d",
"body": "…ogic\n\nThe three cmd/coolify commands that hit real API endpoints (deploy-app,\ndeploy-app-git, update-env) had no tests because the runE bodies all\nend in a network call. Each command does have a non-trivial pure-Go\npreflight step that's worth testing:\n\n- update-env: parseEnvKVs() validates --env KE\n[…]\ne c.UpdateAppEnvs / c.CreateDockerComposeApp /\nc.CreatePrivateGitHubAppApp / c.StartApp call sites, which can be\nmocked via the coolifyAPI interface pattern when an end-to-end test\nbecomes a priority.",
"is_bot": false,
"headline": "test(coolify): cover deploy-app, deploy-app-git, update-env parsing l…",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-28T14:09:23Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "d241e755f0b58da31ab775a7962bf0d831207f5c",
"body": "…+ internal layers\n\nEight bugs + one ineffective test, found by a parallel code-reviewer\nsweep and triaged for >70% confidence. Each fix has a dedicated\nregression test that fails on the bug and passes on the fix.\n\n* cmd/secrets/sync_coolify.go: applyCoolifyDiff() now writes the\n '✓ Applied' line t\n[…]\nd dedupEnvCase already enforces\n last-wins semantics.\n - get.go --write flag: by-design operator-only path.\n - diff.go rotation hint: hint is operationally useful, not a real\n info-disclosure.",
"is_bot": false,
"headline": "fix(secrets,coolify,doctor,git): nine hardening fixes across the cmd …",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-28T14:09:23Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "f6a6a274e69b65a8dbdc2163948c4297bd22b255",
"body": "Two atomic-write hardening fixes that came out of the bug-hunt sweep:\n\n1. WriteFileAtomic now uses os.CreateTemp instead of a fixed temp name.\n The previous '.<base>.tmp' name was deterministic, so two processes\n writing the same target opened and truncated each other's tmp file.\n With CreateT\n[…]\nc. A power loss\n between rename and the kernel's data flush could otherwise leave the\n .env file present but empty — visible disaster for the team since\n .env is part of the trusted file source.",
"is_bot": false,
"headline": "fix(ageutil,source): unique temp names + fsync in WriteFileSource",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-28T14:09:23Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "ea0fc08e2d1c1895d5bdc10f4f2356ad224211da",
"body": "…direct\n\nFive hardening fixes in the coolify client package, found by a parallel\ncode-reviewer sweep:\n\n1. validateUUID enforces UUID-shape (or lax slug for test fixtures) on\n appUUID/envUUID before path concatenation. Closes the URL injection\n vector where a value like '../servers' would resolve\n[…]\nat the entry of every public method that\n concatenates appUUID into a URL path (ListAppEnvs, UpsertAppEnv,\n DeleteAppEnv, UpdateAppEnvs, SetBuildArgs, TriggerDeploy,\n SetCustomLabels, StartApp).",
"is_bot": false,
"headline": "fix(coolify): validate UUIDs, truncate error bodies, strip auth on re…",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-28T14:09:23Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "602eaee8f75ce8eb0fff78fdc9cc0b78ec99e4bb",
"body": "The previous CI bump raised the job timeout, but 'go test' itself has a\ndefault 10m per-package timeout that was killing cmd/secrets midway\nthrough (it takes ~5m with -race due to scrypt-based age.Encrypt in\nfixtures, plus the -v output keeps it streaming for the full duration).\nPass -timeout 15m so go test waits as long as the job allows.",
"is_bot": false,
"headline": "ci: extend go test timeout to 15m (default is 10m)",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-28T13:04:45Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "8fe2dcafd8c91728ede4f60fcc231ce697a4cf36",
"body": "CI was killing the test job at 10m. The cmd/secrets package alone takes\n~5m with -race due to scrypt-based age.Encrypt in fixtures; the new\napply/diff tests pushed total runtime past the limit.\n\nTwo changes:\n - .github/workflows/ci.yml: timeout-minutes 10 → 15\n - cmd/secrets/apply_test.go: remove \n[…]\nded against\n HFS+ second-granularity mtime. Modern filesystems (ext4 on CI, APFS\n on dev) resolve mtime at nanosecond precision; two consecutive\n writes show distinct mtimes without any wait.",
"is_bot": false,
"headline": "ci: bump test timeout to 15m, drop coarse-FS sleep in apply tests",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-28T13:04:45Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "f742c77ea42d9fdea9d6b2e05bd4d813fbfacd01",
"body": "Onboarding doc covers the apply-first / predev-script workflow and adds\na .wapps.yaml reference with the new sections.\n\nAI skill (SKILL.md) and .cursorrules name 'apply' as the preferred way\nto materialize env files; env --write becomes the ad-hoc fallback.\n\ninit template emits a commented-out 'targets:' block so new repos see\nthe option without having to read the docs first.",
"is_bot": false,
"headline": "docs: targets workflow + diff/apply commands",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-28T13:04:45Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "766bb635a7000ba883a849f72d154ba1346ff0c3",
"body": "'wapps secrets diff [ref]' compares archive at a git ref (default HEAD~1)\nto the current working tree. Output shows added/changed/removed key\nnames — values, value hashes, and value lengths never reach stdout.\nChange detection uses sha256(canonical value JSON) in-process.\n\nSafety: gitShowRunner refu\n[…]\ns\nref naming rules already forbid leading dashes, so this never rejects\na legitimate ref.\n\nDecrypt failure across the ref hints at passphrase rotation (which the\ncurrent implementation does not span).",
"is_bot": false,
"headline": "feat(secrets): diff command (AI-safe, key-only)",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-28T13:04:45Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "9b474b3c009519d68e92723a753dfd02fe9317a4",
"body": "Adds 'wapps secrets apply' which materializes every target declared in\n.wapps.yaml's 'targets:' block atomically. Idempotent — files already\nmatching the would-be-written bytes are left alone (mtime untouched) so\nfile watchers (Next.js dev server, Vite HMR) don't spuriously reload.\n\nAfter every arch\n[…]\ncommand. Set/import-env are refactored to return the\nmarshaled payload from encryptAndWriteArchive so the apply step reuses\nthe same bytes — avoids double-marshal divergence in key order across\ncalls.",
"is_bot": false,
"headline": "feat(secrets): apply command + auto-apply hook for set/import-env/sync",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-28T13:04:45Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "fafbabccf075238b66c4720b4881da41f78249a0",
"body": "New optional fields:\n default_prefix: repo-wide prefix used by 'apply' and per-target overrides\n targets: declarative consumption file list (path, optional prefix)\n\nTarget.Prefix is *string so 'unset' and 'explicit empty' are distinguishable\n(needed when default_prefix is non-empty but a specific target wants plain).\n\nValidation: target.path required, no duplicates, '..' rejected.",
"is_bot": false,
"headline": "feat(config): add default_prefix and targets to .wapps.yaml schema",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-28T13:04:45Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "c2d7586664a6db42c36a8994337a1e93aca76af1",
"body": "PROGRESS.md + CHANGELOG.md created to carry session state forward.\nMemory dir bootstrapped at ~/.claude/projects/-Users-adnankurt-Documents-Projects-wapps-cli/memory/\nwith 6 entries (project state, distribution channel, AI skill location,\ndesign doc index, PR pattern preference, cross-repo exploration rule).",
"is_bot": false,
"headline": "chore: refresh trackers + memory before compact",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-28T04:10:01Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "4a40e69a5553a16dd6dbbb1b06d5dae72ec46f7d",
"body": "Previously 'wapps --version' returned \"unknown flag\" — main.go had no\nversion var to inject into, and the .goreleaser.yml ldflag pointed at\nnonexistent main.version (a silent no-op for every prior release).\n\nThis commit:\n- Adds cmd.Version (default \"dev\") and wires rootCmd.Version, which\n makes cob\n[…]\nform\n collision since cobra only adds --version long form when -v is taken\n\nSmoke tests in cmd/root_test.go guard against accidental removal of\nVersion field (which would silently disable --version).",
"is_bot": false,
"headline": "fix: wapps --version flag + correct GoReleaser ldflag target",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-28T04:02:13Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "8f8a9c90dc2e6de88635d1a89762d1e9f5a1737a",
"body": "Implements eng-review T13 (AI integration) and T14 (operator\nonboarding doc). With this commit and the preceding T8/T11/T12/T15\nwork, B.3 closes — wapps-cli has everything it needs for the first\nteammate rollout.\n\n.claude/skills/wapps-secrets/SKILL.md (T13):\n Teaches Claude Code / agents the apply-\n[…]\ned):\n - CONTRIBUTING.md (defer until first external contribution interest)\n - README polish for public release (defer to v1.0.0)\n - Anonymization of internal examples (defer to public-repo cutover)",
"is_bot": false,
"headline": "docs: AI skill + .cursorrules + operator onboarding (T13 + T14)",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-28T03:23:48Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "f7e2b88850ae10692e23760170294c3e042edb13",
"body": "Implements eng-review T10. The --target=coolify flag on\n'wapps secrets sync' pushes archive contents to a Coolify application's\nenv vars, with dry-run-by-default + --force destructive (Issue 2 D3\ndecision in office-hours).\n\nUsage:\n wapps secrets sync --target=coolify --app <uuid> # dry-run\n[…]\nnoop,\n archiveToFlatMap string/list/prefix, applyCoolifyDiff ordering,\n stops on first error)\n\n22 new tests total. SetBuildArgs's 5 existing tests still pass after\nrefactor — abstraction proven.",
"is_bot": false,
"headline": "feat(secrets): sync --target=coolify mirrors archive to Coolify app env",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-28T03:23:48Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "8afd9674d21962c1b8f1d75e932730ce8f7949d3",
"body": "…pers)\n\nT9 in the eng review was scoped to infra-tofu/projects/platform —\noperational work in a different repo. But the CLI gains two helpers\nhere that make platform bootstrap (and any per-repo rollout) a\none-command affair:\n\n wapps secrets init [--with-file-source] [--force]\n wapps doctor --for t\n[…]\nentries, idempotent)\n - doctor --for tofu covered indirectly via PreflightEnv tests\n (the same code path)\n\nOnboarding doc (T14 next commit) will reference both as Step 1/2 of\nthe per-repo rollout.",
"is_bot": false,
"headline": "feat(secrets,doctor): init scaffolder + doctor --for tofu (T9 CLI hel…",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-28T03:23:48Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "cf922d769c240a84e0aa0af392adba48f6712794",
"body": "Implements eng-review T11. After every successful rotate-master,\nappends one JSONL line to <archive-dir>/rotation.log recording who\nrotated, when, against which archives, and with what pp fingerprints.\n\nSchema (versioned):\n schema_version: 1\n ts: RFC3339 UTC timestamp\n actor: $USER from os/user.C\n[…]\nacross two rotations, error when pp same, error when old missing,\nerror when new missing, decrypt failure when wrong old pp, fingerprint\ndeterminism + distinctness, key count for valid + invalid JSON.",
"is_bot": false,
"headline": "feat(secrets): rotate-master writes audit log JSONL",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-28T03:23:48Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "9a8109c4c53f31384c8c1d9560332b97ff24d1a4",
"body": "Implements eng-review T15 — minimal open-source readiness. Public\nrelease (CONTRIBUTING.md, anonymization of internal examples, repo\npublic toggle) deferred until first external interest per design doc.",
"is_bot": false,
"headline": "chore: add MIT LICENSE",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-28T03:23:48Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "57fedcc0225a05dc780505bb91b48aa4b3d8170a",
"body": "Implements eng-review T8 in the D11-narrowed scope (cmd/secrets/*,\ninternal/source/*, internal/ageutil/* — NOT cmd/coolify/, cmd/git/,\ncmd/doctor.go).\n\nDesign choice (post-Codex critique): EXPLICIT redaction via Wrap()\nrather than heuristic auto-redact. Reasons:\n\n - Heuristic regex auto-redact has \n[…]\node paths use safelog at call site. Auto-converting existing\nfmt.Errorf calls would change tested behavior and risk regression for\nno current leak (verified: no existing message quotes secret values).",
"is_bot": false,
"headline": "feat(safelog): explicit redaction primitives for secret-handling paths",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-28T02:44:36Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "d11017a2449ba62562bb5268d42fb5627adff070",
"body": "Implements eng-review T12: archive writes go through one atomic helper.\nPreviously sync.go and rotate.go used bare os.WriteFile which can leave\na truncated archive on power loss / signal kill — catastrophic for a\nsecrets archive. set.go and import-env.go already did temp+rename\ninline, but with dupl\n[…]\nxisting, no .tmp\nleftover on success, temp in same dir as target (cross-fs safety),\nencrypt+write roundtrip, encrypt failure leaves nothing behind, parent\ndir must exist (no auto-mkdir to hide typos).",
"is_bot": false,
"headline": "feat(ageutil): atomic write helper + refactor sync/set/import-env/rotate",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-28T02:44:36Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "2d9a5e3d29dda223f789f2d8809187edf15504a3",
"body": "Implements the exec half of eng-review T7: AI-safe apply primitive that\nruns a subprocess with the decrypted archive injected as env vars. wapps\nitself never prints values; only the subprocess does (and its output is\nthe subprocess's own responsibility — a separate trust boundary).\n\nUsage:\n wapps s\n[…]\ntedEnvOnCollision (last-wins for archive)\n - NoPassphraseErrors\n - EmptyArgsErrors\n - RunnerErrorPropagates\n - buildExecEnv: string/list/null value types, sorted order, malformed\n JSON rejected",
"is_bot": false,
"headline": "feat(secrets): exec -- runs commands with archive env injected",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-28T02:23:50Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "51135f238876aea3d11fe78c143d81fb88f8ecfa",
"body": "Implements the env half of eng-review T7: AI-safe apply primitive that\nwrites secrets to a file without printing any value to stdout. Agents\ncall 'wapps secrets env --write .env.local' instead of relying on the\nshell-redirect pattern (which would show values in the agent transcript\nas the captured t\n[…]\nitten file, no .tmp leftover, missing passphrase, and\n.wapps.yaml dest override.\n\nExisting 5 writeTofuOutputsAsEnv tests updated to pass the new prefix\nparameter (preserving TF_VAR_ default behavior).",
"is_bot": false,
"headline": "feat(secrets): env --write + --prefix flags for AI-safe writes",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-28T02:23:50Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "e191744b63b26b9d855dcde075c20426cf5b7110",
"body": "Implements eng-review T6: 'wapps secrets import-env <file>'. Reuses the\nsame env-file parser the file source adapter uses, so anything that\nimports cleanly via import-env also works as a 'file' source declaration\nin .wapps.yaml (consistency is the whole point of one parser).\n\nUse case: existing repo\n[…]\ntests: happy path with 3 imported + 1 pre-existing keys preserved,\n.wapps.yaml requirement, malformed env file rejected with line N,\nmissing input file error, all-comment file is no-op (not an error).",
"is_bot": false,
"headline": "feat(secrets): import-env for one-shot bulk capture into the archive",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-28T02:11:39Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "50882e8f5950463199846e682567dd9519533973",
"body": "Implements eng-review T5: 'wapps secrets set <KEY>' — the capture half of\nthe capture-discipline insight from /office-hours.\n\nSequence:\n 1. Load .wapps.yaml (required — set has no place in legacy tofu-only mode\n since you can't write back to Tofu state from the CLI)\n 2. Locate single file sour\n[…]\nty drift rejection, drift error propagation, missing\npassphrase, empty value rejection, empty KEY guard, atomic write (no\n.tmp leftover).\n\nDependency: golang.org/x/term v0.43.0 for the no-echo prompt.",
"is_bot": false,
"headline": "feat(secrets): set captures new secret values (interactive, no echo)",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-28T02:11:39Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "e388ca385ab61a0f0c3a542a328ccf86800e2c5a",
"body": "Adds WriteFileSource which lets cmd/secrets/set update a file source after\ncapturing a new key. Per D6.b (eng-review), file sources are\nmachine-managed: naive sorted key=value form, no comment preservation\n(the team agreed not to use inline comments).\n\nBehavior:\n - Reads existing entries via the sa\n[…]\nent.\n\n7 tests: new file with header, sorted append across multiple writes,\noverride of existing key, single-quote escape, preservation of existing\nkeys on append, 0600 mode, atomic (no .tmp leftover).",
"is_bot": false,
"headline": "feat(source): file writer with sorted naive-write + wapps-managed header",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-28T02:11:39Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "33f54aa1dc7942ed25e02650f1ba87374feb11e4",
"body": "Wires the Source/Config abstraction into wapps secrets sync. Two paths:\n\n1. Legacy (no .wapps.yaml present): unchanged behavior — single tofu\n source, dest=secrets/all.enc.age, preflight env check. v0.5.x repos\n continue to work without any operator action.\n\n2. Config-driven (.wapps.yaml present\n[…]\nConfigPath_RejectsBadYAML: malformed config halts, does not\n silently fall back\n\nRefactored emitCommitHint as a private helper so both paths share the\n\"Next: git add ... && git commit\" advice line.",
"is_bot": false,
"headline": "feat(secrets): sync dispatches to .wapps.yaml or legacy tofu",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-28T02:01:15Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "69e90eb4ee333defe82f1af07067b2354fd7302c",
"body": "Builds the abstraction for multi-source secrets (eng-review T4). Each\nSource implementation reads its underlying system (Tofu state, .env file,\nlater: GitHub Secrets, Coolify env) and returns tofu-output-shaped JSON\nthat merges cleanly with other sources.\n\ninternal/source:\n - Source interface (Name\n[…]\niles. Coverage spans happy paths, all error\nbranches (unknown type, missing fields, mutually-exclusive fields,\nmalformed YAML, malformed env file at line N), and the Merge override\ndetection contract.",
"is_bot": false,
"headline": "feat(source,config): introduce Source interface + .wapps.yaml schema",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-28T02:01:15Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "f545bd2ddcdf3598d3f37dfbc2256285cd015a2a",
"body": "…ippet\n\n\\`wapps secrets sync\\` shells out to \\`tofu output -json\\`, which reads\nprovider creds + state-backend creds at startup. Missing env vars\npreviously produced confusing tofu errors that didn't point at the fix:\n \\\"Failed to request input from user for variable var.state_passphrase\\\"\n \\\"No v\n[…]\nspecific var named + hint + script snippet), missing state passphrase,\nall-missing (every required var listed). preflight is dependency-injected\non the env lookup function so tests stay deterministic.",
"is_bot": false,
"headline": "feat(secrets): sync preflight checks required env + emits recovery sn…",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-28T01:58:14Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "bd999123c509a56114a4d80f9f1fbd14e29af99a",
"body": "cmd/secrets/env previously forced every output value to string at unmarshal\ntime, crashing on lists (vaulter_traefik_cert_paths and similar):\n json: cannot unmarshal array into Go struct field .value of type string\n\nFix: value is now json.RawMessage. Strings emit as before\n(export TF_VAR_x='value')\n[…]\niteTofuOutputsAsEnv as a testable helper. 5 tests cover:\nmixed value types (string + list + map + bool + number + null),\nsingle-quote escaping, deterministic ordering, empty input, and\nmalformed JSON.",
"is_bot": false,
"headline": "fix(secrets): env handles non-string Tofu outputs",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-28T01:58:14Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "d68575dc2e4b0d3e8f768b967f7bf1c694941837",
"body": "`git rev-parse HEAD:secrets/all.enc.age` interprets path as git-root-relative\nby default. When called from a subdirectory (e.g. infra-tofu/projects/vaulter\nwhere the archive lives at projects/vaulter/secrets/all.enc.age in git-root\nterms), this fails with \"path exists, but not 'secrets/all.enc.age'\"\n[…]\nession test added: TestDriftFromSubdirectory creates a repo with an\narchive at a nested path and calls HasDrift with the subdirectory as\nrepoPath. Pre-fix: errors out. Post-fix: clean drift detection.",
"is_bot": false,
"headline": "fix(git): HasDrift works from subdirectory cwd",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-28T01:58:14Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "ac209b56718c0f1b6e42ec5425acce4711811def",
"body": "Prior fix (4ec1e1b) used PATCH /envs only, but PATCH returns 404 when\nthe env key doesn't yet exist on the application. New approach:\n- POST /envs first (create); 409 means key already exists\n- On 409, fall back to PATCH /envs (update)\n- Both endpoints require \"is_buildtime\" (not \"is_build_time\")\n\nS\n[…]\nBuildArgs to doBytes error formatting.\n\nResult: SetBuildArgs is now truly idempotent across repeated Tofu\napplies regardless of whether the env key already exists, with\ntype-safe error path detection.",
"is_bot": false,
"headline": "fix(coolify): SetBuildArgs uses POST-then-PATCH for idempotent upsert",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-28T01:58:02Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "4ec1e1b2292f2c2c3cf350511b76f776f4ab0427",
"body": "Probed Coolify v4 (2026-05-26): PATCH /envs/bulk does NOT upsert by key —\nit appends new rows, so repeated runs (Tofu re-applies, CI re-deploys)\nstack up duplicate build args. PATCH /envs (no uuid in path) is upsert\nby key.\n\nAlso: POST/PATCH /envs requires field 'is_buildtime' (not 'is_build_time'\na\n[…]\ndpoint field name inconsistency in\nCoolify v4 — documented in the function doc.\n\nOne HTTP call per build arg now, but catalog is small (~3 per service)\nand idempotency is more important than batching.",
"is_bot": false,
"headline": "fix(coolify): SetBuildArgs uses PATCH /envs (upsert) not /envs/bulk",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-26T00:35:16Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "04304a3bd47e91f4cd919c7e8657fd0e102c24f9",
"body": "Coolify v4 has no dedicated build args field on the Application create body\n(probed: build_args, build_pack_buildargs, docker_build_args,\ndockerfile_target_build_args, buildargs all return 422 'field not allowed').\n\nBuild args in Coolify are stored as env vars with is_build_time=true,\nPATCHed via /a\n[…]\n-PATCH with is_build_time=true\n - TriggerDeploy(appUUID) — GET /deploy?uuid=...\n\nTests: SetBuildArgs sends correct shape + skips malformed; empty list is no-op;\nTriggerDeploy hits the right endpoint.",
"is_bot": false,
"headline": "feat(coolify): add --build-arg flag to deploy-app-git",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-26T00:26:39Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "2c917b72fd42b099737bda2a34be99992ff41a13",
"body": "Adds wapps coolify deploy-app-git → POST /applications/private-github-app.\nCoolify v4 builds the application from a private GitHub repo on the target\nserver (e.g. vaulter-app-01 native arm64), no GHCR pull needed.\n\nRequired for Phase B pivot — vaulter-api 19 services deployed via Coolify\nGitHub App source build instead of GHA-pre-built image + GHCR pull.",
"is_bot": false,
"headline": "feat(coolify): deploy-app-git command for private GitHub source builds",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-25T23:59:40Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "4ca57af787060da18e6e747ebaf134f29a904a69",
"body": "Coolify v4 /api/v1/applications returns a top-level JSON array, not the\n{\"data\": [...]} envelope shape that the client assumed. The fallback branch\nreturned nil silently, so import-app emitted 0 imports against real Coolify\neven with the destination.server.uuid fix in v0.3.0.\n\nAdded doRaw + doBytes \n[…]\n and\nregression tests TestListApplications_TopLevelArray /\nTestListApplications_DataEnvelope to lock both paths.\n\nUpdated TestImportApp_ServerUUIDFromDestination to use the real top-level\narray shape.",
"is_bot": false,
"headline": "fix(coolify): ListApplications handles top-level JSON array response",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-25T22:30:44Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "84a556299fad112445ae5ea48f0f53abc291104d",
"body": "Phase A discovery: Coolify v4 /api/v1/applications response nests server_uuid\nunder destination.server.uuid, but wapps-cli was reading a[\"server_uuid\"]\n(top-level) which is null. Filter --server-uuid emitted 0 imports for any\nvalue. Now correctly navigates the nested path.\n\nAdded regression test TestImportApp_ServerUUIDFromDestination to lock the\ncorrect path.",
"is_bot": false,
"headline": "fix(coolify): import-app reads server_uuid from destination.server.uuid",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-25T22:27:43Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "b7e4343a975bf9be2f6ac9947fe2179f63339f2f",
"body": "…stubs)",
"is_bot": false,
"headline": "feat(coolify): import-app command (list + emit Tofu imports.sh + HCL …",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-25T19:06:16Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "42b14ee2c17d6109d1052a3ff019ca03fab81d3f",
"body": "…ands",
"is_bot": false,
"headline": "feat(coolify): set-labels (with certresolver strip) + update-env comm…",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-25T19:05:40Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f7049ff6e4286cc441f3ed87ffb820c55337f19e",
"body": null,
"is_bot": false,
"headline": "feat(coolify): deploy-app command (dockercompose create + start)",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-25T19:05:04Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "db47132084aaf2c2e566997823acb8fc6dd38f10",
"body": null,
"is_bot": false,
"headline": "feat(coolify): REST client with create/patch/start/list primitives",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-25T19:04:13Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "51c6da5bdd2dae78407d3c7da803728a5ec9cfee",
"body": "Default homebrew formula directory is repo root, but mixing with README.md\nand other root files prevents 'brew tap' auto-discovery (verified: had to\nmanually mv wapps.rb -> Formula/wapps.rb during v0.1.0 release to make\n'brew install wapps' work). Setting directory: Formula makes future\nreleases (v0.2.0+) push the formula directly to Formula/wapps.rb, no\nmanual intervention needed.",
"is_bot": false,
"headline": "ci(goreleaser): brews[].directory = Formula",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-25T19:01:07Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f1e2cb25d664aae6fd2a7480079da1c97645c663",
"body": "GoReleaser v2 default uses GITHUB_TOKEN for SCM ops, but cross-repo formula\npush to wappsdev/homebrew-tap needs a PAT with cross-repo write scope.\nSet brews[0].repository.token = {{ .Env.HOMEBREW_TAP_PAT }} explicitly so\nGoReleaser uses the PAT for the formula push step (the auto GITHUB_TOKEN\nonly has repo scope on wapps-cli itself, hence the previous 403).\n\nAlso pinned the formula commit identity to wapps-release-bot@wapps.co.",
"is_bot": false,
"headline": "fix(ci): explicit HOMEBREW_TAP_PAT token in brews repository config",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-25T18:55:06Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "fa4107376d8b303392664498c0e9a30b31bc1e69",
"body": "- .goreleaser.yml: cross-compile linux+darwin × amd64+arm64, archive as\n tar.gz with versioned names, sha256 checksums, brew formula published to\n wappsdev/homebrew-tap with assert-help test recipe.\n- release.yml: triggered on v* tags, uses HOMEBREW_TAP_PAT secret for\n formula push.\n- ci.yml: PR + main push runs vet + race-test + build for fast feedback.\n\nNote: HOMEBREW_TAP_PAT secret must be set before the first v0.1.0 tag push\n(handled by controller; see Phase A plan Task 19 Step 4-5).",
"is_bot": false,
"headline": "ci: GoReleaser config + release + CI workflows",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-25T18:45:07Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "652554deff47cb99e97b122e020be6520b6ea055",
"body": "…nt wraps\n\n- internal/git/git.go: error wraps now follow Layer.Method convention\n (git.HasDrift: fetch / git.Pull: / git.fileSha: ref:file) matching the\n rest of the codebase (ageutil, secrets, tofu packages).\n- internal/git/git.go: fileSha error suppression narrowed — only swallows\n 'does not ex\n[…]\n\n- cmd/git/status.go: now prints 'not inside a git repository — drift check\n skipped' instead of leaking raw 'fatal: not a git repository' when run\n outside a repo (e.g. wapps git status from /tmp).",
"is_bot": false,
"headline": "fix(git): narrow fileSha error suppression + IsRepo helper + consiste…",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-25T18:42:41Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "d38131017b2757f5cf00f79183162181b2744aaf",
"body": null,
"is_bot": false,
"headline": "feat(git): wapps git status command",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-25T18:39:21Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "5bb79d98511888144a3a28f64f8cd85b4e56b28a",
"body": null,
"is_bot": false,
"headline": "feat(git): auto-sync preflight (fetch + pull on drift)",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-25T18:38:30Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "75536b6d6d6602de2462e15cb500044c9ac64b77",
"body": null,
"is_bot": false,
"headline": "feat(secrets): add env (dump) + rotate-master subcommands",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-25T18:37:19Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "ac755297e2cab783ac4b605f76e3fd9fd745fd8e",
"body": "…d tidy\n\n- doctor.go: handle http.NewRequest error (prevents nil-pointer panic when\n COOLIFY_URL is malformed); use switch for cleaner err/5xx/ok branches;\n always close response body via explicit Close before status check.\n- secrets/sync.go: add comment explaining the dateFmt = '+' + '%Y-%m-%d'\n \n[…]\nvet's printf format-string warning while emitting\n the literal shell snippet $(date +%Y-%m-%d) for the user's shell to expand.\n- go.mod: tidy removed unused viper deps + indirect transitive packages.",
"is_bot": false,
"headline": "fix(cli): doctor nil-pointer + sync.go vet workaround comment + go mo…",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-25T18:35:24Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "ac3200bda56e6f9cc86dc7f205a486ad75a01e77",
"body": null,
"is_bot": false,
"headline": "feat(secrets): add get/list/verify commands",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-25T18:28:54Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "15c8884dd568571afc9b7983efbe8b13fc4ceb31",
"body": null,
"is_bot": false,
"headline": "feat(secrets): wapps secrets sync — tofu output → age archive",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-25T18:27:56Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "0bc191f57b9c299dd5177e2d9ff8af8daa8626c8",
"body": null,
"is_bot": false,
"headline": "feat(ageutil): scrypt-based encrypt/decrypt helpers",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-25T18:26:08Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "47f132849e8c5ec7abba4cf9430db1cea9797ef0",
"body": null,
"is_bot": false,
"headline": "feat(doctor): end-to-end dependency + access check",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-25T18:25:32Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "426dd667e3141630af6790e71334b1d6e2dfea64",
"body": null,
"is_bot": false,
"headline": "feat: cobra root command + global flags",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-25T18:24:58Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "61b945eba442074665e0d495d2461628154ae693",
"body": null,
"is_bot": false,
"headline": "feat: bootstrap wapps-cli Go module",
"author_name": "Adnan Kurt",
"author_login": "adnankurt16",
"committed_at": "2026-05-25T17:21:16Z",
"body_truncated": false,
"is_coding_agent": false
}
],
"releases_count": 23,
"commits_last_year": 87,
"latest_release_at": "2026-07-13T12:33:11Z",
"latest_release_tag": "v0.19.0",
"releases_from_tags": false,
"days_since_last_push": 14,
"active_weeks_last_year": 7,
"days_since_latest_release": 14,
"mean_days_between_releases": 4.4
},
"community": {
"has_readme": true,
"has_license": true,
"has_description": true,
"has_contributing": false,
"health_percentage": 37,
"has_issue_template": false,
"has_code_of_conduct": false,
"has_pull_request_template": false
},
"ecosystem": {
"packages": [
{
"name": "github.com/wappsdev/wapps-cli",
"exists": true,
"license": null,
"keywords": [],
"ecosystem": "go",
"matches_repo": true,
"registry_url": "https://pkg.go.dev/github.com/wappsdev/wapps-cli",
"is_deprecated": false,
"latest_version": "v0.19.0",
"repository_url": "https://github.com/wappsdev/wapps-cli",
"versions_count": 23,
"total_downloads": null,
"dependents_count": null,
"deprecation_note": null,
"maintainers_count": null,
"monthly_downloads": null,
"first_published_at": null,
"latest_published_at": "2026-07-13T12:31:55Z",
"latest_version_yanked": null,
"days_since_latest_publish": 14
}
]
},
"popularity": {
"forks": 0,
"stars": 0,
"watchers": 0,
"fork_history": {
"days": [],
"complete": true,
"collected": 0,
"total_forks": 0
},
"star_history": {
"days": [],
"complete": true,
"collected": 0,
"total_stars": 0,
"collected_at": null
},
"open_issues_and_prs": 0
},
"ai_readiness": {
"has_nix": false,
"example_dirs": [],
"has_llms_txt": false,
"has_dockerfile": false,
"has_mcp_signal": false,
"bootstrap_files": [],
"api_schema_files": [],
"has_devcontainer": false,
"typecheck_configs": [
"worker/tsconfig.json"
],
"toolchain_manifests": [
"go.mod"
],
"largest_source_bytes": 35832,
"source_files_sampled": 199,
"oversized_source_files": 0,
"agent_instruction_files": [
".cursorrules"
],
"agent_instruction_max_bytes": 1639
},
"dependencies": {
"manifests": [
"go.mod",
"worker/package.json"
],
"advisories": {
"error": null,
"scope": null,
"source": null,
"findings": [],
"collected": false,
"malicious": [],
"truncated": false,
"by_severity": {},
"advisory_count": 0,
"affected_count": 0,
"assessed_count": 0,
"malicious_count": 0,
"assessed_package": null,
"unassessed_count": 0,
"direct_affected_count": 0
},
"ecosystems": [
"go",
"npm"
],
"dependencies": [
{
"name": "filippo.io/age",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.3.1"
},
{
"name": "github.com/spf13/cobra",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.10.2"
},
{
"name": "github.com/stretchr/testify",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.11.1"
},
{
"name": "golang.org/x/crypto",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.45.0"
},
{
"name": "golang.org/x/term",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.37.0"
},
{
"name": "gopkg.in/yaml.v3",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v3.0.1"
},
{
"name": "@noble/ciphers",
"manifest": "worker/package.json",
"ecosystem": "npm",
"version_constraint": "2.0.1"
},
{
"name": "@noble/hashes",
"manifest": "worker/package.json",
"ecosystem": "npm",
"version_constraint": "^1.8.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": 33,
"open_issues": 0,
"closed_ratio": null,
"closed_issues": 0,
"closed_unmerged_prs": 1
},
"bus_factor": 1,
"bot_contributors": 0,
"top_contributors": [
{
"type": "User",
"login": "adnankurt16",
"commits": 87,
"avatar_url": "https://avatars.githubusercontent.com/u/8597614?v=4"
}
],
"contributors_sampled": 1,
"top_contributor_share": 1
},
"quality_signals": {
"has_ci": true,
"has_tests": true,
"ci_workflows": [
"ci.yml",
"release.yml"
],
"has_docs_dir": true,
"linter_configs": [],
"has_editorconfig": false,
"has_linter_config": false,
"has_precommit_config": false
},
"security_signals": {
"lockfiles": [
"go.sum"
],
"scorecard": {
"checks": [
{
"name": "Binary-Artifacts",
"score": 10,
"reason": "no binaries found in the repo",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
},
{
"name": "Branch-Protection",
"score": 0,
"reason": "branch protection not enabled on development/release branches",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
},
{
"name": "CI-Tests",
"score": 10,
"reason": "20 out of 20 merged PRs checked by a CI test -- score normalized to 10",
"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/26 approved changesets -- score normalized to 0",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
},
{
"name": "Contributors",
"score": 3,
"reason": "project has 1 contributing companies or organizations -- score normalized to 3",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
},
{
"name": "Dangerous-Workflow",
"score": 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": 0,
"reason": "project was created within the last 90 days. Please review its contents carefully",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
},
{
"name": "Packaging",
"score": 10,
"reason": "packaging workflow detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
},
{
"name": "Pinned-Dependencies",
"score": 0,
"reason": "dependency not pinned by hash detected -- score normalized to 0",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
},
{
"name": "SAST",
"score": 0,
"reason": "SAST tool is not run on all commits -- score normalized to 0",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
},
{
"name": "Security-Policy",
"score": 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": 0,
"reason": "Project has not signed or included provenance with any releases.",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
},
{
"name": "Token-Permissions",
"score": 0,
"reason": "detected GitHub workflow tokens with excessive permissions",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
},
{
"name": "Vulnerabilities",
"score": 0,
"reason": "30 existing vulnerabilities detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
}
],
"commit": "db07ff7e9202b19860ea58cf411672589d122c8c",
"ran_at": "2026-07-28T05:47:24Z",
"aggregate_score": 2.7,
"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-13T13:22:20Z",
"oldest_open_prs": [],
"last_merged_pr_at": "2026-07-13T13:02:57Z",
"ci_last_conclusion": "SUCCESS",
"oldest_open_issues": []
}
},
"config": {
"disabled_metrics": [],
"disabled_categories": [],
"disabled_components": {}
},
"source": {
"url": "https://github.com/wappsdev/wapps-cli",
"host": "github.com",
"name": "wapps-cli",
"owner": "wappsdev"
},
"metrics": {
"overall": {
"key": "overall",
"band": "at_risk",
"name": "Overall health",
"note": null,
"notes": [],
"value": 49,
"inputs": {
"security": 27,
"vitality": 67,
"community": 24,
"governance": 51,
"engineering": 67
},
"components": []
},
"categories": [
{
"key": "vitality",
"band": "moderate",
"name": "Vitality",
"value": 67,
"weight": 0.22,
"metrics": [
{
"key": "development_activity",
"band": "moderate",
"name": "Development activity",
"note": null,
"notes": [],
"value": 51,
"inputs": {
"commits_last_year": 87,
"human_commit_share": 1,
"days_since_last_push": 14,
"active_weeks_last_year": 7
},
"components": [
{
"key": "push_recency",
"name": "Push recency",
"detail": "last push 14 days ago",
"points": 28.8,
"status": "partial",
"details": [
{
"code": "push_recency",
"params": {
"days": 14
}
}
],
"max_points": 36
},
{
"key": "commit_cadence",
"name": "Commit cadence",
"detail": "7/52 weeks with commits",
"points": 4.8,
"status": "partial",
"details": [
{
"code": "commit_cadence_weeks",
"params": {
"weeks": 7
}
}
],
"max_points": 36
},
{
"key": "commit_volume",
"name": "Commit volume",
"detail": "87 commits in the last year",
"points": 17.5,
"status": "partial",
"details": [
{
"code": "commits_last_year",
"params": {
"count": 87
}
}
],
"max_points": 18
},
{
"key": "openssf_scorecard_maintained",
"name": "OpenSSF Scorecard: Maintained",
"detail": "project was created within the last 90 days. Please review its contents carefully",
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
}
]
},
{
"key": "release_discipline",
"band": "excellent",
"name": "Release discipline",
"note": null,
"notes": [],
"value": 90,
"inputs": {
"releases_count": 23,
"latest_release_tag": "v0.19.0",
"releases_from_tags": false,
"days_since_latest_release": 14,
"mean_days_between_releases": 4.4
},
"components": [
{
"key": "ships_releases",
"name": "Ships releases",
"detail": "23 releases published",
"points": 27,
"status": "met",
"details": [
{
"code": "releases_published",
"params": {
"count": 23
}
}
],
"max_points": 27
},
{
"key": "release_recency",
"name": "Release recency",
"detail": "latest release 14 days ago",
"points": 36,
"status": "met",
"details": [
{
"code": "release_recency",
"params": {
"days": 14
}
}
],
"max_points": 36
},
{
"key": "release_cadence",
"name": "Release cadence",
"detail": "a release every ~4.4 days",
"points": 27,
"status": "met",
"details": [
{
"code": "release_cadence",
"params": {
"gap": 4.4
}
}
],
"max_points": 27
},
{
"key": "openssf_scorecard_signed_releases",
"name": "OpenSSF Scorecard: Signed-Releases",
"detail": "Project has not signed or included provenance with any releases.",
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
}
]
},
{
"key": "abandonment",
"band": "excellent",
"name": "Abandonment",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"cap": null,
"state": "unverified",
"guards": [],
"signals": [],
"red_flag": false,
"multiplier_pct": 100,
"declared_reason": null,
"unverified_reason": "repository_too_young",
"unanswered_open_prs": null,
"unanswered_open_issues": null,
"days_since_last_merged_pr": null,
"days_since_last_human_commit": null,
"days_since_last_human_commit_is_floor": false
},
"components": [
{
"key": "project_is_still_maintained",
"name": "Project is still maintained",
"detail": "maintenance record not established from the collected data",
"points": 100,
"status": "met",
"details": [
{
"code": "abandonment_unverified",
"params": {}
}
],
"max_points": 100
}
]
}
],
"description": "Is the project alive — is code being written and are releases shipping?"
},
{
"key": "community",
"band": "critical",
"name": "Community & Adoption",
"value": 24,
"weight": 0.18,
"metrics": [
{
"key": "popularity",
"band": "critical",
"name": "Popularity & adoption",
"note": null,
"notes": [],
"value": 1,
"inputs": {
"forks": 0,
"stars": 0,
"watchers": 0,
"growth_state": "unverified",
"growth_factor_pct": 100,
"growth_unverified_reason": "no_history"
},
"components": [
{
"key": "stars",
"name": "Stars",
"detail": "0 stars",
"points": 0,
"status": "missed",
"details": [
{
"code": "stars",
"params": {
"count": 0
}
}
],
"max_points": 60
},
{
"key": "forks",
"name": "Forks",
"detail": "0 forks",
"points": 0,
"status": "missed",
"details": [
{
"code": "forks",
"params": {
"count": 0
}
}
],
"max_points": 25
},
{
"key": "watchers",
"name": "Watchers",
"detail": "0 watchers",
"points": 0,
"status": "missed",
"details": [
{
"code": "watchers",
"params": {
"count": 0
}
}
],
"max_points": 15
}
]
},
{
"key": "community_health",
"band": "moderate",
"name": "Community health",
"note": null,
"notes": [],
"value": 50,
"inputs": {
"has_readme": true,
"has_license": true,
"has_contributing": false,
"has_issue_template": false,
"has_code_of_conduct": false,
"has_pull_request_template": false
},
"components": [
{
"key": "readme",
"name": "README",
"detail": null,
"points": 22.5,
"status": "met",
"details": [],
"max_points": 22.5
},
{
"key": "license",
"name": "License",
"detail": "recognized license (MIT)",
"points": 22.5,
"status": "met",
"details": [
{
"code": "license_standard",
"params": {}
},
{
"code": "license_spdx",
"params": {
"spdx": "MIT"
}
}
],
"max_points": 22.5
},
{
"key": "contributing_guide",
"name": "CONTRIBUTING guide",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 18
},
{
"key": "code_of_conduct",
"name": "Code of conduct",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 13.5
},
{
"key": "issue_template",
"name": "Issue template",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.2
},
{
"key": "pr_template",
"name": "PR template",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 6.3
}
]
}
],
"description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
},
{
"key": "governance",
"band": "moderate",
"name": "Sustainability & Governance",
"value": 51,
"weight": 0.24,
"metrics": [
{
"key": "maintainer_resilience",
"band": "critical",
"name": "Maintainer resilience (bus factor)",
"note": null,
"notes": [],
"value": 13,
"inputs": {
"bus_factor": 1,
"contributors_sampled": 1,
"top_contributor_share": 1
},
"components": [
{
"key": "bus_factor",
"name": "Bus factor",
"detail": "1 contributor(s) cover half of all commits",
"points": 9,
"status": "partial",
"details": [
{
"code": "bus_factor",
"params": {
"count": 1
}
}
],
"max_points": 54
},
{
"key": "commit_distribution",
"name": "Commit distribution",
"detail": "top contributor authored 100% of commits",
"points": 0,
"status": "missed",
"details": [
{
"code": "top_contributor_share",
"params": {
"share": 100
}
}
],
"max_points": 22.5
},
{
"key": "contributor_breadth",
"name": "Contributor breadth",
"detail": "1 contributors",
"points": 1.4,
"status": "partial",
"details": [
{
"code": "contributors_sampled",
"params": {
"count": 1
}
}
],
"max_points": 13.5
},
{
"key": "openssf_scorecard_contributors",
"name": "OpenSSF Scorecard: Contributors",
"detail": "project has 1 contributing companies or organizations -- score normalized to 3",
"points": 3,
"status": "partial",
"details": [],
"max_points": 10
}
]
},
{
"key": "responsiveness",
"band": "good",
"name": "Issue & PR responsiveness",
"note": "Excluded from scoring (no data or not applicable): Issue resolution. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"issue_resolution"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 70,
"inputs": {
"merged_prs": 33,
"open_issues": 0,
"closed_issues": 0,
"issue_closed_ratio": null,
"closed_unmerged_prs": 1
},
"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": "33/34 decided PRs merged",
"points": 37.1,
"status": "partial",
"details": [
{
"code": "decided_prs_merged",
"params": {
"merged": 33,
"decided": 34
}
}
],
"max_points": 38.25
},
{
"key": "openssf_scorecard_code_review",
"name": "OpenSSF Scorecard: Code-Review",
"detail": "Found 0/26 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": 39,
"inputs": {
"followers": 2,
"owner_type": "Organization",
"is_verified": null,
"owner_login": "wappsdev",
"public_repos": 3,
"account_age_days": 194
},
"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": "2 followers of wappsdev",
"points": 3.4,
"status": "partial",
"details": [
{
"code": "owner_followers",
"params": {
"count": 2,
"login": "wappsdev"
}
}
],
"max_points": 25
},
{
"key": "track_record",
"name": "Track record",
"detail": "3 public repos, account ~0 yr old",
"points": 5.4,
"status": "partial",
"details": [
{
"code": "public_repos",
"params": {
"count": 3
}
},
{
"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": [
"github.com/wappsdev/wapps-cli"
],
"ecosystems": "go",
"any_deprecated": false,
"min_days_since_publish": 14
},
"components": [
{
"key": "published_resolvable",
"name": "Published & resolvable",
"detail": "1 package(s) on go",
"points": 25,
"status": "met",
"details": [
{
"code": "packages_published",
"params": {
"count": 1,
"ecosystems": "go"
}
}
],
"max_points": 25
},
{
"key": "publish_recency",
"name": "Publish recency",
"detail": "latest publish 14 days ago",
"points": 35,
"status": "met",
"details": [
{
"code": "publish_recency",
"params": {
"days": 14
}
}
],
"max_points": 35
},
{
"key": "version_history",
"name": "Version history",
"detail": "23 published versions",
"points": 20,
"status": "met",
"details": [
{
"code": "published_versions",
"params": {
"count": 23
}
}
],
"max_points": 20
},
{
"key": "not_deprecated",
"name": "Not deprecated",
"detail": "active, not deprecated or yanked",
"points": 20,
"status": "met",
"details": [
{
"code": "package_not_deprecated",
"params": {}
}
],
"max_points": 20
}
]
}
],
"description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
},
{
"key": "engineering",
"band": "moderate",
"name": "Engineering Quality",
"value": 67,
"weight": 0.2,
"metrics": [
{
"key": "engineering_practices",
"band": "moderate",
"name": "Engineering practices",
"note": null,
"notes": [],
"value": 68,
"inputs": {
"has_ci": true,
"has_tests": true,
"has_editorconfig": false,
"has_linter_config": false,
"has_precommit_config": false
},
"components": [
{
"key": "ci_workflows",
"name": "CI workflows",
"detail": "2 workflow(s)",
"points": 24,
"status": "met",
"details": [
{
"code": "ci_workflows",
"params": {
"count": 2
}
}
],
"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": null,
"points": 0,
"status": "missed",
"details": [],
"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": "20 out of 20 merged PRs checked by a CI test -- score normalized to 10",
"points": 20,
"status": "met",
"details": [],
"max_points": 20
}
]
},
{
"key": "documentation",
"band": "moderate",
"name": "Documentation",
"note": null,
"notes": [],
"value": 65,
"inputs": {
"topics": [],
"has_wiki": false,
"homepage": null,
"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": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 15
},
{
"key": "repository_description",
"name": "Repository description",
"detail": null,
"points": 10,
"status": "met",
"details": [],
"max_points": 10
},
{
"key": "topics",
"name": "Topics",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
},
{
"key": "wiki",
"name": "Wiki",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
}
]
}
],
"description": "Are baseline engineering and documentation practices in place?"
},
{
"key": "security",
"band": "critical",
"name": "Security",
"value": 27,
"weight": 0.16,
"metrics": [
{
"key": "security_posture",
"band": "critical",
"name": "Security posture",
"note": null,
"notes": [],
"value": 27,
"inputs": {
"source": "openssf_scorecard",
"checks_evaluated": 18,
"scorecard_version": "v5.5.0",
"checks_inconclusive": 0,
"scorecard_aggregate": 2.7
},
"components": [
{
"key": "binary_artifacts",
"name": "Binary-Artifacts",
"detail": "no binaries found in the repo",
"points": 7.5,
"status": "met",
"details": [],
"max_points": 7.5
},
{
"key": "branch_protection",
"name": "Branch-Protection",
"detail": "branch protection not enabled on development/release branches",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "ci_tests",
"name": "CI-Tests",
"detail": "20 out of 20 merged PRs checked by a CI test -- score normalized to 10",
"points": 2.5,
"status": "met",
"details": [],
"max_points": 2.5
},
{
"key": "cii_best_practices",
"name": "CII-Best-Practices",
"detail": "no effort to earn an OpenSSF best practices badge detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 2.5
},
{
"key": "code_review",
"name": "Code-Review",
"detail": "Found 0/26 approved changesets -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "contributors",
"name": "Contributors",
"detail": "project has 1 contributing companies or organizations -- score normalized to 3",
"points": 0.8,
"status": "partial",
"details": [],
"max_points": 2.5
},
{
"key": "dangerous_workflow",
"name": "Dangerous-Workflow",
"detail": "no 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": "project was created within the last 90 days. Please review its contents carefully",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "packaging",
"name": "Packaging",
"detail": "packaging workflow 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 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "sast",
"name": "SAST",
"detail": "SAST tool is not run on all commits -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "security_policy",
"name": "Security-Policy",
"detail": "security policy file not detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "signed_releases",
"name": "Signed-Releases",
"detail": "Project has not signed or included provenance with any releases.",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "token_permissions",
"name": "Token-Permissions",
"detail": "detected GitHub workflow tokens with excessive permissions",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "vulnerabilities",
"name": "Vulnerabilities",
"detail": "30 existing vulnerabilities detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
}
]
}
],
"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": 74,
"weight": 0,
"metrics": [
{
"key": "ai_agent_context",
"band": "excellent",
"name": "Agent context & guidance",
"note": null,
"notes": [],
"value": 85,
"inputs": {
"has_llms_txt": false,
"legible_history_share": 1,
"agent_instruction_files": [
".cursorrules"
],
"agent_instruction_max_bytes": 1639
},
"components": [
{
"key": "agent_instructions",
"name": "Agent instructions",
"detail": ".cursorrules",
"points": 45,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": ".cursorrules"
}
}
],
"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": "87 of 87 human commits state their intent (structured subject or explanatory body)",
"points": 40,
"status": "met",
"details": [
{
"code": "legible_history",
"params": {
"legible": 87,
"sampled": 87
}
}
],
"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": [
"go.sum"
],
"has_dockerfile": false,
"typed_language": true,
"bootstrap_files": [],
"has_devcontainer": false,
"has_linter_config": false,
"typecheck_configs": [
"worker/tsconfig.json"
],
"agent_commit_share": 0,
"toolchain_manifests": [
"go.mod"
],
"dependency_bot_commit_share": 0
},
"components": [
{
"key": "one_command_bootstrap",
"name": "One-command bootstrap",
"detail": "go.mod (toolchain convention, no task runner)",
"points": 12.6,
"status": "partial",
"details": [
{
"code": "toolchain_convention",
"params": {
"files": "go.mod"
}
}
],
"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": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 11
},
{
"key": "static_type_checking",
"name": "Static type checking",
"detail": "worker/tsconfig.json",
"points": 11,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "worker/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 87",
"points": 0,
"status": "missed",
"details": [
{
"code": "no_agent_authored_commits",
"params": {
"sampled": 87
}
}
],
"max_points": 10
},
{
"key": "automated_maintenance",
"name": "Automated maintenance",
"detail": "no automated dependency updates observed",
"points": 0,
"status": "missed",
"details": [
{
"code": "no_dependency_automation",
"params": {}
}
],
"max_points": 8
},
{
"key": "openssf_scorecard_pinned_dependencies",
"name": "OpenSSF Scorecard: Pinned-Dependencies",
"detail": "dependency not pinned by hash detected -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
}
]
},
{
"key": "ai_code_legibility",
"band": "excellent",
"name": "Code legibility for models",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"primary_language": "Go",
"largest_source_bytes": 35832,
"source_files_sampled": 199,
"oversized_source_files": 0
},
"components": [
{
"key": "type_checkable_code",
"name": "Type-checkable code",
"detail": "Go (statically typed)",
"points": 45,
"status": "met",
"details": [
{
"code": "statically_typed_language",
"params": {
"language": "Go"
}
}
],
"max_points": 45
},
{
"key": "manageable_file_sizes",
"name": "Manageable file sizes",
"detail": "0/199 source files over 60KB",
"points": 55,
"status": "met",
"details": [
{
"code": "oversized_source_files",
"params": {
"kb": 60,
"sampled": 199,
"oversized": 0
}
}
],
"max_points": 55
}
]
}
],
"description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
}
],
"metrics_version": "1.13.0"
},
"warnings": [
"GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository"
],
"report_type": "repository",
"generated_at": "2026-07-28T05:47:39.095947Z",
"schema_version": "0.27.0",
"badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/w/wappsdev/wapps-cli.svg",
"full_name": "wappsdev/wapps-cli",
"license_state": "standard",
"license_spdx": "MIT"
}