Dependency Automation for Release-Pinned Installs
AppTheory and the rest of the Theory Cloud framework stack distribute TypeScript and Python packages as immutable GitHub Release assets, not through npm or PyPI publication. Consumers that pin release tarballs and wheels need a release-aware dependency bot; otherwise direct URLs stay invisible until a human edits them.
Use Renovate’s github-releases datasource with regex managers. Dependabot can still help with ordinary registry
packages in your application, but it does not provide an equivalent custom manager for AppTheory’s tarball/wheel URLs.
Renovate config
Put this in renovate.json (or merge the same fields into your existing Renovate config):
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"customManagers": [
{
"customType": "regex",
"description": "AppTheory GitHub Release asset URLs and Go module tags",
"managerFilePatterns": [
"/(^|/)(package\\.json|package-lock\\.json|requirements\\.txt|pyproject\\.toml|go\\.mod)$/"
],
"matchStrings": [
"github\\.com/theory-cloud/AppTheory/releases/download/v(?<currentValue>\\d+\\.\\d+\\.\\d+(?:-rc(?:\\.\\d+)?)?)",
"github\\.com/theory-cloud/apptheory/v6\\s+v(?<currentValue>\\d+\\.\\d+\\.\\d+(?:-rc(?:\\.\\d+)?)?)",
"theory-cloud-apptheory(?:-cdk)?-(?<currentValue>\\d+\\.\\d+\\.\\d+)\\.tgz",
"apptheory(?:_cdk)?-(?<currentValue>\\d+\\.\\d+\\.\\d+)-py3-none-any\\.whl"
],
"depNameTemplate": "theory-cloud/AppTheory",
"datasourceTemplate": "github-releases",
"versioningTemplate": "semver"
},
{
"customType": "regex",
"description": "TableTheory GitHub Release asset URLs and Go module tags",
"managerFilePatterns": [
"/(^|/)(package\\.json|package-lock\\.json|requirements\\.txt|pyproject\\.toml|go\\.mod)$/"
],
"matchStrings": [
"github\\.com/theory-cloud/TableTheory/releases/download/v(?<currentValue>\\d+\\.\\d+\\.\\d+(?:-rc\\.\\d+)?)",
"github\\.com/theory-cloud/tabletheory\\s+v(?<currentValue>\\d+\\.\\d+\\.\\d+(?:-rc\\.\\d+)?)",
"theory-cloud-tabletheory(?:-ts)?-(?<currentValue>\\d+\\.\\d+\\.\\d+)\\.tgz",
"tabletheory_py-(?<currentValue>\\d+\\.\\d+\\.\\d+)-py3-none-any\\.whl"
],
"depNameTemplate": "theory-cloud/TableTheory",
"datasourceTemplate": "github-releases",
"versioningTemplate": "semver"
}
],
"packageRules": [
{
"description": "Review AppTheory and TableTheory release pins together",
"matchPackageNames": ["theory-cloud/AppTheory", "theory-cloud/TableTheory"],
"groupName": "Theory Cloud framework release pins"
}
]
}
This config intentionally matches both direct release assets and Go module requirements:
github.com/theory-cloud/apptheory/v6 v4.0.0
https://github.com/theory-cloud/AppTheory/releases/download/v4.0.0/theory-cloud-apptheory-4.0.0.tgz
https://github.com/theory-cloud/AppTheory/releases/download/v4.0.0/theory-cloud-apptheory-cdk-4.0.0.tgz
https://github.com/theory-cloud/AppTheory/releases/download/v4.0.0/apptheory-4.0.0-py3-none-any.whl
https://github.com/theory-cloud/AppTheory/releases/download/v4.0.0/apptheory_cdk-4.0.0-py3-none-any.whl
Each release asset URL carries the version twice — once in the download/v<version> tag path and once in the file name.
A regex manager updates one occurrence per matchString, so the config above matches both: the tag-relative strings
and the release-version file-name strings (*-<version>.tgz, *-<version>-py3-none-any.whl). Without the file-name
strings, a bump rewrites only the tag path, leaves the file name pinned to the old version, and produces an asset URL
that 404s — the install path fails closed rather than silently pinning a stale asset. Pre-release lines normalize the
Python wheel file name pre-release suffix differently (-rc becomes rc0), so treat a pre-release bump as needing a
manual check of the file name.
When Renovate opens a bump PR, keep AppTheory’s runtime package, CDK package, and generated lockfiles in the same PR. If your app also consumes TableTheory directly, review that bump in the same change so TableTheory data-layer pins and AppTheory runtime/CDK pins do not drift independently.
Checksum discipline
Renovate can move URLs, but it cannot prove that your downloaded release assets still match SHA256SUMS.txt. Keep the
checksum verification step from the install docs in your CI or bootstrap script:
VERSION=4.0.0
TAG="v${VERSION}"
PYTHON_VERSION="${VERSION/-rc/rc0}"
gh release download "${TAG}" --repo theory-cloud/AppTheory --pattern "SHA256SUMS.txt" --clobber
grep -E " (theory-cloud-apptheory-${VERSION}\\.tgz|apptheory-${PYTHON_VERSION}-py3-none-any\\.whl)$" SHA256SUMS.txt | sha256sum -c -
For npm lockfiles, run npm install after Renovate updates the release URL so package-lock.json records the new
integrity. For Python, keep the wheel URL in requirements.txt or pyproject.toml and verify the downloaded release
asset before installing it in production bootstrap.
The TypeScript package’s .npmrc sets npm’s allow-remote policy to root. This is the narrow permission required for
the integrity-pinned TableTheory GitHub Release tarball: transitive dependencies remain unable to introduce remote URL
fetches.
Dependabot notes
Dependabot remains useful for ordinary registry dependencies such as aws-cdk-lib, constructs, or application-only
npm packages. It is not the single path for AppTheory because AppTheory intentionally does not publish npm or PyPI
registry packages. Do not replace the GitHub Release pins with registry coordinates to make Dependabot work; use
Renovate for the release-pinned framework assets and Dependabot only for the dependencies that already come from a
registry.
Maintainer override notes
AppTheory only carries package-manager overrides while a current audit, compatibility, or deterministic-build gate
requires them. In SP17, the TypeScript runtime package removed stale transitive overrides after the regenerated lockfile
passed npm audit with zero vulnerabilities. The removal rationale was:
@typescript-eslint/typescript-estree→minimatch: upstream now resolves tominimatch@10.2.5, so the local pin was no longer carrying a security fix.@eslint/eslintrc/eslint→ajv: ESLint selects its compatibleajv@6.14.0; AppTheory does not override lint-tool internals without an active advisory.@eslint/config-array/eslint/eslint-plugin-import-x→minimatch: the lint stack remains audit-clean on its upstream-selectedminimatchversions, and none of these packages are runtime dependencies.fast-xml-parser/fast-xml-builder: the regenerated TypeScript lockfile no longer contains those packages, so keeping orphan overrides would hide dependency graph drift instead of fixing it.flatted/js-yaml: upstream-selected lint-tool transitive versions remain audit-clean; local pins were redundant.yaml: the TableTheory release asset now resolvesyaml@2.9.1; AppTheory should not override TableTheory’s transitive dependency unless a current advisory or contract gate requires it.
The repository pins AWS CDK 2.273.0, whose published tarball bundles the patched brace-expansion@5.0.12. That meets
the documented removal condition of the former brace-expansion 5.0.9 bundled-dependency exception (operator-ruled
2026-10-03), so that exception is retired - standard maintenance, not a new exception grant. The CDK npm-audit and
GovTheory OSV gates still verify the exact bundled graph, now as a positive assertion (brace-expansion >= 5.0.12),
and accept exactly one reviewed, self-expiring exception - braces 3.0.3 reached only through the
jsii-pacmak / jsii-rosetta / fast-glob / micromatch dev chain (operator-ruled 2026-10-04) - carrying a hard
recheck_by 2026-11-02 and a registry-backed removal condition (see
gov-infra/planning/apptheory-10of10-rubric.md SEC-2). Any vulnerable bundle, AWS CDK, minimatch, brace-expansion,
package-path, or finding drift fails closed.
The TypeScript lint graph no longer carries a minimatch@3.x parent. Landing the eslint 10 train
(eslint 10.11.0, @eslint/js 10.0.1, eslint-plugin-unicorn ^76.0.0) with eslint-plugin-import swapped for the
maintained eslint-plugin-import-x fork dropped @eslint/eslintrc and hoisted the whole lint stack onto one
minimatch@10.2.6 → brace-expansion@5.0.12 path. The vulnerable brace-expansion@1.1.17 instance and the
GHSA-rgw5-rvv9-x895 / GHSA-mh99-v99m-4gvg exception that covered it are therefore gone, and the ts/ SEC-2 checker
now grants no exception: it requires both an empty OSV report and the exact parent, minimatch, brace-expansion, and
version graph, and any drift fails closed. The ts/ lockfile class is therefore exception-free and advisory-variant
independent, because the only remaining brace-expansion instance (5.0.12) is past every recorded 5.x fix; the
aws-cdk lockfile class carries only the remaining braces 3.0.3 jsii-toolchain exception.