Refactor static to publish @polygonlabs/meta with typed ABIs#182
Conversation
`scripts/codegen.mjs` walks the `network/` JSON tree and emits
`src/abi/<chain>/<network>/<type>/<Contract>.ts` plus
`src/info/<chain>/<network>.ts` with `as const` literal exports,
backed by an inline round-trip self-test that fails the build on any
JSON->TS drift.
JSON stays the source of truth. Both `src/abi/` and `src/info/` are
gitignored so generated artifacts never enter git -- only the JSON
files in `network/` are authored. This keeps the existing
static.polygon.technology HTTP endpoint working (nginx still serves
the JSON tree) while also giving npm consumers typed `as const`
ABIs at build time.
The `as const` assertion on every emitted ABI is load-bearing, not
stylistic. Without it, TypeScript widens the array element type to a
generic `{ type: string; name: string; inputs: ...[] }` shape, and
viem/wagmi/abitype cannot extract function names, argument types, or
return types at the call site -- the whole point of typed ABIs
disappears. With `as const`, every string literal stays at its exact
value and the array becomes a tuple, giving consumers full type-level
inference for `readContract({ abi, functionName, args })` and friends.
The legacy `Network` class is preserved for dynamic name-based
lookup but ported to ESM TS with a private constructor and a static
`Network.create()` async factory -- the constructor cannot `await`
the per-network info import. `artifacts()` and `abi()` are async,
backed by `await import('./abi/<...>.js')`. Documented as a breaking
change in the upcoming MIGRATION.md.
`"type": "module"` is set on the package because verbatimModuleSyntax
(via @tsconfig/node-ts) refuses ESM syntax otherwise. The legacy
CommonJS `network/index.js` and the unused `minify.js` are removed
in this commit.
Build pipeline: `pnpm run build` = codegen then `tsc -p
tsconfig.build.json`. `prepack` (added in the next commit) runs
`build` so `pnpm publish` always emits a fresh dist.
The package moves from `@maticnetwork/meta@2.4.82` to
`@polygonlabs/meta@1.0.0`. The numbering resets because the surface
and runtime requirements change in ways that are not drop-in
upgradable; a continuity bump would mislead consumers into expecting
a compatible release.
The HTTP endpoint at static.polygon.technology continues to serve
the same JSON files unchanged. This commit affects only the npm
package surface.
Subpath exports:
".": dist/index.{js,d.ts} -- Network class entry
"./abi/*": dist/abi/<chain>/<net>/<type>/* -- typed ABIs per contract
"./info/*": dist/info/<chain>/<net> + /networks -- typed metadata
"./network/*": network/* -- raw JSON, identical
paths to @maticnetwork/meta
The first three import the codegenned, `as const`-typed TS modules
that viem/wagmi/abitype need. The fourth keeps the raw JSON path
working for consumers who want bytes, not types -- same path scheme
as the previous `@maticnetwork/meta@2.x` package and the public
HTTP endpoint, so a JSON consumer migrates by changing only the
package name.
Published `files`: `dist/`, `network/`, MIGRATION.md, README.md,
CHANGELOG.md. Source files, tsconfigs, the codegen script, plans,
and supply-chain config stay in-repo.
`publishConfig.access: "public"` and `publishConfig.provenance: true`
are set so that `changeset publish` from CI uses npm OIDC trusted
publishing and stamps each release with provenance metadata.
MIGRATION.md and README.md both carry a "Why `as const`" section so
consumers see the typing rationale at the migration step. CONTRIBUTING.md
documents the codegen flow: edit JSON in `network/`, run `pnpm run
codegen`, never hand-edit the gitignored `src/abi/` or `src/info/`.
Adds the team-standard release flow used across all `@polygonlabs/*` packages. Developers add a `.changeset/<name>.md` to each PR that ships a user-visible change; on merge to `master`, the `apps-npm-release.yml` shared workflow opens a "Version Packages" PR that bumps the version, writes the changelog, and deletes consumed changeset files. Merging *that* PR triggers the publish: the workflow calls `changeset publish`, which tags the release as `@polygonlabs/meta@<version>` and pushes to npm via OIDC trusted publishing with provenance. No manual `npm publish`, no manual tagging, no static `NPM_AUTH_TOKEN` secret. Trigger files call `0xPolygon/pipelines` directly because that repo is public; verbatim local copies are unnecessary. Both triggers declare explicit `permissions:` and pass secrets by name -- never `secrets: inherit` -- so the credential surface granted to the shared workflow is visible at a glance. The bundled initial-rename changeset describes the rename from @maticnetwork/meta and the breaking changes (ESM-only, Node >=24, async Network class). The HTTP endpoint at static.polygon.technology is explicitly noted as unchanged. The legacy `npm-release.yml` (Node 12, GitHub Release-triggered, raw `npm publish`, unpinned action versions) is deleted in this same commit per the team standard against leaving superseded workflows in place as "disabled" fallbacks. `baseBranch` in `.changeset/config.json` is `master` because this repo predates the team's master->main rename convention; the rename is a separate PR.
17a4a51 to
0c1d7e5
Compare
`package.json` version drops from 1.0.0 to 0.0.0 so the existing
`major` changeset produces 1.0.0 on the Version Packages PR rather
than 2.0.0. Empirically confirmed: changeset version applied to
`0.0.0 + major` yields `1.0.0`; minor yields 0.1.0; patch yields
0.0.1. Major is the right bump for the rename narrative anyway.
Plan section "First-release bootstrap" rewritten to document the
team-canonical flow:
1. Locally publish 1.0.0-dev.0 with --tag dev to claim the npm
package name and become package admin.
2. Configure the trusted publisher on the package's settings page
(now accessible via package-admin role, no org-admin needed).
3. Monday's CI publish goes through OIDC cleanly; changesets/action
creates the GitHub Release from CHANGELOG.md.
Fallback if the trusted publisher isn't ready by Monday: accept the
CI 403, run `pnpm exec changeset publish` locally, then run
`@polygonlabs/sync-github-releases release <repo> <tag> --apply` to
populate the GitHub Release body byte-equal to what
changesets/action would have produced. That's the documented team
recovery path; we've adopted it as the safety net.
EventsHub is the staking-system contract that emits the newer `*WithId`
event variants (`ShareBurnedWithId`, `DelegatorUnstakeWithId`,
`SharesTransfer`, `UpdateCommissionRate`) which carry the unbond nonce —
critical for the PIP-85 staker-pool subgraph in 0xPolygon/subgraphs to
attribute share movements correctly. The proxy addresses are already in
the registries (`Main.Contracts.EventsHubProxy` on both mainnet/v1 and
testnet/amoy), but the ABI was missing, leaving downstream consumers
(notably the new `pos-staking` subgraph) blocked.
ABI sourced from the legacy `maticnetwork/subgraphs` repo, which has
indexed the same deployed contract for years; events match the wire
format the impl emits behind the proxy. `pnpm run codegen` regenerates
the `src/abi/{mainnet/v1,testnet/amoy}/plasma/EventsHub.ts` modules
(gitignored, not in this commit).
Addresses two SonarCloud Security Hotspots flagged on PR #182 with real input validation rather than NOSONAR suppressions. src/Network.ts: tightens the Network class API surface so a caller cannot path-traverse the abi tree via the dynamic import. Adds exported `Chain` and `ArtifactType` literal-union types, an `/^[A-Za-z0-9_]+$/` regex on contract names, an allowlist check on artifact types via a `asserts type is ArtifactType` user-defined guard, and a registry-membership check on Network.create. Each rejection throws a TypeError with a helpful message naming the expected shape (and, for unknown networks, the known set). scripts/codegen.mjs: adds a confine() helper that resolves derived paths against an explicit base and throws if the resolved path escapes the base. Wraps every read and write so a `..` directory entry or a malicious symlink under network/ cannot read or write outside the network/, src/abi/, or src/info/ roots. Also flips the Array.isArray failure to TypeError to satisfy S7786. Build still emits 469 ABI + 4 info + 1 networks modules, runtime smoke confirms AccessControl@pos returns 11 entries on the happy path and `../etc/passwd`, bogus types, and unknown chains all reject with TypeError.
MaximusHaximus
left a comment
There was a problem hiding this comment.
Added a few things in-line
Also:
- We need a CI workflow that runs our test & typecheck flow which verifies that our 'build/codegen' process succeeds as a PR check plus any other smoke-level testing that would make sense for the package
- Please nest the
metapackage inpackages/metadir rather than making this a single-package repository that contains a mixture of published and unpublished content at the root - Ideally the package would be committed to the repo intact, in a known-good state, where we can inspect exactly what the package being published is without needing to run codegen. Also, the entire package should be
.tsfiles, not a mixture of.jsand.ts; it's not clear to me why there is a mixture of both kinds of files here. See 0xPolygon/pipelines#41 for an approach to detect codegen drift explicitly (I need review on that PR anyway BTW :) 👍 )
| src/abi/ | ||
| src/info/ |
There was a problem hiding this comment.
Please nest all generated code into a generated directory for clarity
| } | ||
| } | ||
|
|
||
| export class Network { |
There was a problem hiding this comment.
🔪 this entire abstraction can go and be replaced with an explicit, declarative set of paths exports. E.g. if I need addresses I can import from /addresses, if I need ABIs I can import from /abi/...
Per PR review feedback, plans/ shouldn't host long-lived fixtures; durable info belongs in CLAUDE.md, MIGRATION, or README.
Per PR review, all generated code now lives under a single `generated` directory so the boundary between hand-authored and codegenned source is obvious at a glance. Public subpath exports (`./abi/*`, `./info/*`) are unchanged — only the dist mapping moves.
Per PR review, the Network/factory abstraction added nothing the
existing typed deep imports under ./abi/* and ./info/* don't already
provide. Consumers reach addresses, ABIs, and per-network metadata
through declarative subpath exports — fully typed, sync, and
tree-shakable. The package no longer has a root entry point.
BREAKING CHANGE: `import { Network } from '@polygonlabs/meta'` is
removed. Replace with `import { abi } from '@polygonlabs/meta/abi/<chain>/<network>/<type>/<Contract>'`
and `import { info } from '@polygonlabs/meta/info/<chain>/<network>'`.
…/meta/ Per PR review, the npm-published surface and the HTTP-endpoint surface now live in separate top-level directories so what gets shipped to npm is obvious at a glance. - packages/meta/ holds the @polygonlabs/meta source, network/ JSON tree, codegen script, and the package's own README / MIGRATION / CONTRIBUTING. - The repo root keeps Dockerfile / nginx.conf / index.html for the static.polygon.technology HTTP endpoint, plus a workspace-only root package.json and tsconfig.json. The Dockerfile now COPYs from packages/meta/network so both surfaces still read the same JSON. Per-package tsconfig extends ../../tsconfig.json and tsconfig.build.json gets composite: true so the root config can declare a project reference. repository.directory in the published package now points at packages/meta.
Per PR review, the package should not contain a mixture of .js and .ts sources. The codegen script is the only .mjs file under packages/meta; moving it to .ts removes the mixture. Explicit parameter and return types make the script signature self-documenting. Node 24 strips types natively, so `node scripts/codegen.ts` runs unchanged without a transpiler. tsconfig.json now includes scripts/ so `tsc --noEmit` typechecks the script alongside src/.
Per PR review, the published package contents are now committed so reviewers can inspect the exact .ts modules that will ship without running codegen locally. The codegen step becomes a PR-gate verifier, not a build-time emitter: - src/generated/ is no longer gitignored; 476 files (471 ABI + 4 info + networks) land alongside the network/ JSON they derive from. - codegen-drift-check script regenerates and runs git diff --exit-code -- src/generated. Drift in either direction (edited JSON without regen, or hand-edited generated .ts) fails the gate. - .gitattributes marks packages/meta/src/generated/** as linguist-generated so GitHub collapses it in the PR diff by default and excludes it from language stats. Reviewers can still expand individual files when needed. - codegen:watch (chokidar-cli) re-runs codegen ~200 ms after any network/**/*.json save, so editing JSON keeps in-editor types accurate without a manual rebuild. - CONTRIBUTING.md documents the committed-generated workflow and the watcher.
Closes the Priority 1 config-alignment gap from the /assess-repo audit. - ESLint v10 + @polygonlabs/apps-team-lint at root and per-package (packages/meta/eslint.config.js with tsconfigRootDir set), ignoring the generated tree. - Prettier, markdownlint-cli2, commitlint — all using the team's shared `@polygonlabs/apps-team-lint` exports, no per-repo overrides. - Husky pre-commit (lint-staged + typecheck), commit-msg (commitlint), pre-push (changeset status against origin/master). - Root scripts mirror the template: lint runs lint:md / lint:ts / typecheck / prettier --check via concurrently; format applies all three auto-fixers. `pnpm -r --if-present` propagates per-package typecheck and build, so packages/meta now exposes a `typecheck` script. - pnpm-workspace overrides katex@^0.16.38 and the template's trustPolicyExclude list, both needed once markdownlint-cli2 is installed. Existing markdown and HTML reformatted to satisfy the new gates; workflow YAML normalised by prettier (whitespace + quote style only, no semantic change).
MaximusHaximus
left a comment
There was a problem hiding this comment.
- Leave
networkat the top level of the repo so that this isn't a breaking path change for anyone consuming the data directly from the repository - Codegen the NPM package contents from the repository root into the package
- Per our earlier discussions
/asses-repothis branch and make sure the rest of our team tooling is added (linting, formatting for TS and MD files, typechecking, etc etc.)
| writeTs(outPath, 'abi', srcJson.abi); | ||
|
|
||
| const roundTripped = readTsLiteral(outPath, 'abi'); | ||
| if (JSON.stringify(roundTripped) !== JSON.stringify(srcJson.abi)) { |
There was a problem hiding this comment.
These stringify checks feel a bit insane / redundant -- we just wrote the file on L96, right? How could it possibly not match? If writeTs is sane then this can never fail; same for L122 below.
| try { | ||
| types = listDirs(artifactsPath); | ||
| } catch { | ||
| continue; |
There was a problem hiding this comment.
Why would we silently continue execution in this case? An error hear means that we just failed to update the artifacts for a path we expect to contain them, meaning that our codegen will not be correct (only some paths will be re-generated). IMO this should be an error state; we don't want to make this defensive, because the result could be publishing packages with a mixture of updates and out-of-date actual codegen'd data.
| try { | ||
| info = JSON.parse(readFileSync(indexPath, 'utf8')); | ||
| } catch { | ||
| continue; |
There was a problem hiding this comment.
As above, silently continuing in this case is not desirable; we shouldn't be trying to parse files that are not well-formed, and if we have malformed files in the target directory our codegen should fail loudly to avoid us publishing corrupt/incomplete packages without realising it.
| console.log(`networks: ${stats.networks}`); | ||
| if (stats.mismatches.length > 0) { | ||
| console.error(`\nMISMATCHES (${stats.mismatches.length}):`); | ||
| for (const m of stats.mismatches) console.error(` ${m}`); |
There was a problem hiding this comment.
Ironically, the abovementioned 'silent error swallowing' continue statements mean that this is basically guaranteed to never actually fire -- any real errors encountered are 100% ignored and the mismatches is never incremented, no error state is tracked at all, and this just basically tests 'does JSON.stringify work` :(
| - Node ≥ 24 | ||
| - ESM consumer (use `import`, not `require`) | ||
|
|
||
| If you can't be ESM yet, stay on `@maticnetwork/meta@2.x` for now or |
There was a problem hiding this comment.
I think it's worth noting that consumers can probably still bundle this ESM-native package into their app even if that app is bundled to CommonJS -- we just don't publish CommonJS code from the package; it's up to them. I don't think it's a good idea to recommend they stay on the deprecated package for this reason
…onsistency Addresses the inline review comments on codegen.ts and the top-level "keep network/ at the repo root" / "codegen from repo root into the package" feedback. - network/ moves back to the repo root, restoring direct-from-GitHub consumers and the previous Dockerfile COPY path. The npm package no longer owns the source-of-truth tree. - codegen.ts now reads <repo-root>/network/networks.json as the canonical registry and walks each entry's <chain>/<version>/ directory. A missing index.json, missing artifacts/ directory, empty artifact type directory, or non-array `abi` field is a hard error — silent `continue` swallowed real codegen failures and would have shipped packages with a mixture of fresh and stale generated TS. - The round-trip stringify self-test is gone. writeTs writes the file one line earlier; re-reading + JSON.stringify-comparing is dead weight that only ever caught determinism of JSON.stringify, never any real bug. - A new step at the end of codegen mirrors the repo-root network/ tree into packages/meta/network/ (gitignored, materialised by prepack) so the @polygonlabs/meta/network/* subpath export still resolves to the same paths consumers of @maticnetwork/meta@2.x use. - CONTRIBUTING.md and root README.md updated for the new layout.
Per review feedback, the old wording recommended staying on the deprecated @maticnetwork/meta@2.x for any consumer who "can't be ESM yet". That overstates the constraint — modern bundlers (esbuild, webpack 5+, Vite, Rollup, Parcel) consume ESM packages from CJS host code transparently. The only consumers actually blocked are unbundled Node runtimes that load via `require()` and older bundlers without ESM support; for those the HTTP endpoint remains the documented escape hatch.
MaximusHaximus
left a comment
There was a problem hiding this comment.
Just one thing re: the pnpm minimumReleaseAge, then I think this is ready to go
| - 'packages/*' | ||
|
|
||
| blockExoticSubdeps: true | ||
| minimumReleaseAge: 1440 |
There was a problem hiding this comment.
Adjust to 1 week please (per recent guidelines from security team) :)
Wires up the PR-gate workflows from 0xPolygon/pipelines that every apps-team repo is expected to consume: - ci-trigger.yml — lint / typecheck / test via the ci composite action - codegen-drift-check-trigger.yml — regenerates and fails on any diff under packages/meta/src/generated - claude-code-review-trigger.yml — automated PR review - claude-trigger.yml — @claude mention handler The legacy AWS+GCP push-triggered deploy workflows stay as-is for now; this PR only adds the missing PR-gate surface so future PRs get linted/typechecked/drift-checked before merge.
Brings the AWS ECS deployment workflows up to the team-standard for
permissions and secrets. The push-triggered AWS+GCP deploy plumbing
itself is unchanged — that's a separate decision documented in the PR
description.
- build_and_deploy.yml: top-level `permissions: { contents: read,
id-token: write }` for OIDC; declares its `build_params_gh_secret_keys`
workflow_call secret explicitly and forwards it by name to the
shared `ecs_deploy_docker_taskdef.yaml` instead of `secrets: inherit`.
- deployment.yml: same top-level `permissions:` block; passes
`build_params_gh_secret_keys` explicitly to `build_and_deploy.yml`.
`deployment_gcp.yml` already has the correct `permissions:` block and
doesn't use `secrets: inherit`, so it's unchanged.
Required by team-standards. Every PR against master now requires approval from @0xPolygon/product-applications. Single owner block at the root since the team owns both the npm package and the static.polygon.technology HTTP endpoint that ships from this repo.
Lets Claude sessions running outside the apps-team-workspace fetch the team-standards gist and find their bearings in this repo. The new CLAUDE.md covers the dual-surface architecture (npm package + nginx HTTP endpoint), the codegen flow (repo-root network/ → tracked src/generated/ + gitignored network/ mirror), and points at the existing CONTRIBUTING / MIGRATION / README docs. .claude/settings.json grants WebFetch access to gist.githubusercontent.com so the fetch at the top of CLAUDE.md succeeds without prompting.
Increases the install-time embargo on freshly-published packages from 1440 minutes (24 hours) to 10080 minutes (7 days). The minimumReleaseAgeExclude allow-list still lets internal scopes (@polygonlabs, @maticnetwork, @agglayer, @0xsequence, @0xtrails) through immediately so day-to-day workspace development isn't slowed down.
|
The 1.0.0 release fired Static Deployment on master and it failed
with `startup_failure` immediately — the called
`0xPolygon/pipelines/.github/workflows/ecs_deploy_docker_taskdef.yaml`
declares `permissions: { id-token: write, contents: write }` on its
job, but PR 0xPolygon#182 hardened the trigger with `contents: read`, which is
not a superset of what the called workflow needs.
Both deployment.yml and build_and_deploy.yml now declare
`contents: write`. id-token: write is unchanged. The token is still
scoped down from `inherit`-everything to just the two scopes the AWS
deploy actually uses.


Summary
Refactors
0xPolygon/staticto publish a typed-ABI npm package as@polygonlabs/meta@1.0.0, replacing@maticnetwork/meta@2.x. Each contract's ABI is shipped as anas constTypeScript module soviem/wagmi/abitypeconsumers get full type-level inference at the call site.The public HTTP endpoint at
https://static.polygon.technology/...continues to serve the same JSON files unchanged. Nothing changes for consumers fetching JSON over HTTPS.Architecture
network/is the source of truth. The same files served by the HTTP endpoint.scripts/codegen.mjswalksnetwork/at build time and emitssrc/abi/<chain>/<network>/<type>/<Contract>.ts(eachexport const abi = [...] as const;) plussrc/info/<chain>/<network>.tsandsrc/info/networks.ts. Bothsrc/abi/andsrc/info/are gitignored — generated artifacts never enter git.tsc -p tsconfig.build.jsoncompiles the codegenned TS todist/.prepackrunspnpm run build(codegen + tsc), sopnpm publishalways emits a fresh dist.JSON.stringify-compares to source, failing the build on any drift.Net: JSON authored once, both transports (npm + HTTP) ship the same data.
Subpath exports
Why
as const?Each generated ABI module looks like:
The trailing
as constis load-bearing, not stylistic. Without it, TypeScript widens the array element type to a generic{ type: string; name: string; inputs: ...[] }, which meansviem/wagmi/abitypecannot extract function names, argument types, or return types at the call site — the whole point of shipping typed ABIs disappears. Withas const, every string literal stays at its exact value and the array becomes a tuple, giving consumers full type-level inference forreadContract({ abi, functionName, args })and friends.MIGRATION.mdandREADME.mdboth carry this rationale so consumers see it at the install/migrate step.CONTRIBUTING.mddocuments that the codegen always emits the trailingas constautomatically — don't hand-editsrc/abi/, it's gitignored and regenerated.Commit-by-commit walkthrough
chore: add implementation plan and gitignore ad-hoc plans— commits the session-portable execution plan toplans/refactoring-with-polygonlabs-renaming.mdfor cross-session continuity.chore: migrate from npm to pnpm—.nvmrc=24,pnpm-workspace.yamlwith the team supply-chain block,.npmrcwithlink-workspace-packages=false,pnpm-lock.yamlreplacespackage-lock.json.feat: add TypeScript toolchain—tsconfig.{json,build.json}extending@tsconfig/node24+@tsconfig/node-ts, TS 6.0.3 +@types/node@^24as devDeps.feat: add JSON→TS codegen and ESM Network class—scripts/codegen.mjs(committed, runs at build time),src/Network.ts(async ESM port of legacy class),src/index.ts. Legacynetwork/index.jsandminify.jsdeleted.feat!: rename package to @polygonlabs/meta with subpath exports— newpackage.json,MIGRATION.md,CONTRIBUTING.md, rewrittenREADME.md. Subpath exports for./abi/*,./info/*,./network/*, root.feat: adopt changesets and tag-driven npm release—.changeset/config.json,.changeset/initial-rename.md(major bump), thin trigger workflows calling0xPolygon/pipelines'sapps-npm-release.ymlandapps-changeset-check.ymldirectly. Legacynpm-release.ymldeleted.What's untouched (deferred)
Per "rest later" direction, these stay for follow-up PRs:
Dockerfile,nginx.conf,.github/workflows/{deployment,deployment_gcp,build_and_deploy}.yml,.github/taskdef/*— HTTP-endpoint serving infrastructure, exact-revert from any earlier branch state.secrets: inherit, missingpermissions:, unpinned action SHAs)..github/CODEOWNERSwith@0xPolygon/product-applications.require_code_owner_reviews,enforce_admins:false)..claude/settings.json, rootCLAUDE.md).Test plan
rm -rf node_modules dist src/abi src/info && pnpm install --frozen-lockfile && pnpm run buildfrom a clean checkout — green; codegen emits 469 ABIs + 4 info + 1 networks; tsc emits 476.js+ 476.d.ts.dist/abi/mainnet/v1/pos/AccessControl.d.tsretains the fullreadonly [{ readonly anonymous: false; ... }]as consttuple type.node): static import of typed ABI returns 11 entries;info.Main.ChainIdtyped as1;Network.create('mainnet','v1')populates dynamic keys;network.abi('AccessControl', 'pos')byte-matches the static import; raw JSON viaimport x from '...network/.../X.json' with { type: 'json' }byte-matches both.pnpm pack --dry-runshipsdist/,network/(474 JSON files),MIGRATION.md,README.md,CHANGELOG.md(or absent),package.json— nosrc/,tsconfig*,scripts/,node_modules/,plans/.pnpm exec changeset statusreportsPackages to be bumped at major: @polygonlabs/meta. Note:package.jsonversion is0.0.0on this branch (intentional — the major changeset bumps it to1.0.0on the Version Packages PR). Empirically confirmed:0.0.0 + major = 1.0.0viapnpm exec changeset version.apps-changeset-checkpasses (initial changeset present); theapps-npm-releaseworkflow only runs onpush: masterso it does not fire on PR.First-release bootstrap
This is the first publish of
@polygonlabs/meta, so a few mechanics need a one-time setup. The team-canonical pattern (documented inapps-team-packages/packages/sync-github-releases/README.md) is being followed.Pre-merge (one-time, performed locally before reviewer approval)
To unblock the OIDC publish on Monday without needing org-admin role on
@polygonlabs:The first publish makes the publisher (an npm Member of the
@polygonlabsorg) package admin for@polygonlabs/meta. As package admin, the trusted publisher can be configured per-package without org-admin:0xPolygon/staticnpm-release-trigger.yml@polygonlabs/meta@1.0.0-dev.0is also useful as a downstream-app validation artifact under thedevdist-tag — does not affectnpm install @polygonlabs/meta(which resolves tolatest, unset until 1.0.0 ships).Post-merge (automatic on
masterpush)apps-npm-release.ymlfires →changesets/actionopens "Version Packages" PR (0.0.0 → 1.0.0, generatesCHANGELOG.mdfrom the changeset body, deletes.changeset/initial-rename.md).hasChangesets == false→ publish step runs.@polygonlabs/meta@1.0.0lands on npm with provenance, becomes thelatestdist-tag.changesets/actioncreates the GitHub Release with body extracted fromCHANGELOG.md.Fallback (only if trusted publisher not configured by Monday)
The CI publish 403s on auth. Recover locally:
sync-github-releasespopulates the GitHub Release body byte-equal to whatchangesets/actionwould have produced, so the published release looks identical regardless of which path was taken.Other follow-ups
CHANGESET_RELEASE_BOT_APP_IDandCHANGESET_RELEASE_BOT_APP_PRIVATE_KEYorg secrets are accessible to0xPolygon/static(used byapps-npm-release.ymlto open the Version Packages PR with signed commits).await import()with computed paths insrc/Network.tsandreadFileSync/writeFileSyncwith computed paths inscripts/codegen.mjs. Mark as Safe in the SonarCloud UI when convenient.History note
An earlier draft of this PR proposed deleting the
static.polygon.technologyHTTP endpoint and committing TS source files directly (no codegen). That was reversed because the HTTP endpoint is in active use; the cost of cutting it carries unknown blast radius. The branch was force-pushed to drop the deprecation commits and replace them with the codegen approach. Theplans/refactoring-with-polygonlabs-renaming.mdfile in this PR captures the architecture decision and history.