Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions .github/lanes.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"$schema": "https://raw.githubusercontent.com/tinyland-inc/site.scaffold/main/docs/schemas/lanes.schema.json",
"schema_version": 1,
"spoke": {
"name": "jesssullivan-github-io",
"domain": "transscendsurvival.org",
"image_repository": "ghcr.io/jesssullivan/jesssullivan-github-io-shadow-tailnet"
},
"defaults": {
"runner_class": "tinyland-nix",
"ttl_hours": 72,
"flywheel_target_classes": ["sveltekit-app-build", "sveltekit-unit-tests"]
},
"lanes": [
{
"name": "check",
"trigger": "pull_request",
"theme": "pine",
"snapshot_source": "checked-in",
"e2e": false,
"extra": {
"npm_script": "remote:check",
"public_variant": "remote:check:public",
"note": "Type/build-smoke authority. spoke-ci does not read `extra`; this records the existing script this lane stands for so the mapping is reviewable in one place."
}
},
{
"name": "test",
"trigger": "pull_request",
"theme": "pine",
"snapshot_source": "checked-in",
"e2e": false,
"extra": {
"npm_script": "remote:test",
"public_variant": "remote:test:public",
"note": "Unit, graph-hygiene, workflow-authority, and browser-smoke authority."
}
},
{
"name": "e2e",
"trigger": "pull_request",
"theme": "pine",
"snapshot_source": "checked-in",
"e2e": true,
"extra": {
"npm_script": "remote:e2e",
"public_variant": "remote:e2e:public",
"note": "Playwright Chromium end-to-end authority. spoke-ci's own playwright job stays disabled until a KVM-capable class is anchored for this repo."
}
}
]
}
73 changes: 73 additions & 0 deletions .github/workflows/spoke-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# TIN-3914 spoke-ci adoption: wired here, not yet servable.
#
# Additive by design. `.github/workflows/ci.yml` keeps the substrate-boundary,
# bazel-remote-gates, and build-and-test jobs exactly as they are, so every
# required check and the exact-source production/rollback proofs that consume
# them are untouched while this lane is proven.
#
# This cannot go green until a `jesssullivan-blog-nix` ARC scale set is applied
# in Jesssullivan/jesssullivan-infra
# (tofu/stacks/arc-runners/jesssullivan.tfvars). `tinyland-nix` is the
# capability label those runners will carry; nothing serves it for this
# repository today, so every job below queues until that apply lands.
name: Spoke CI (TIN-3914)

on:
push:
branches: [main]
pull_request:
branches: [main]

permissions:
contents: read
statuses: write

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
ci:
# Pinned by the v3.1.0 tag's commit rather than by the tag name:
# scripts/test-workflow-authority.mjs requires every non-local `uses:` in
# this directory to resolve to a 40-hex commit, reusable workflows
# included. d8d178c is `git rev-parse v3.1.0^{commit}` in
# tinyland-inc/ci-templates. Note this freezes the workflow body only --
# spoke-ci@v3.1.0 resolves its own composite actions at floating `@v3`.
uses: tinyland-inc/ci-templates/.github/workflows/spoke-ci.yml@d8d178c022a0f84853d53a2c8fe0fc90115f0949 # v3.1.0
with:
node_version: '22'
flywheel_config: flywheel
cache_backed: true
lanes_path: .github/lanes.json
default_runner_class: tinyland-nix
# This account publishes one capability class. The template default sends
# bazel-graph to `tinyland-nix-heavy`, which serves no repository in this
# forge scope, so the base label is passed here too.
heavy_runner_class: tinyland-nix
# The template default names //:sveltekit_types and //:svelte_check_test.
# Neither target exists in this repo; these three are its real
# flywheel-eligible CAS surface (BUILD.bazel).
cache_backed_targets: '//:node_modules //:sveltekit_check //:sveltekit_vite_build_smoke'
# No `secrets: inherit`, deliberately diverging from the gftb-site
# exemplar. This workflow carries a pull_request trigger, and this repo's
# standing contract is that a PR-triggered lane reaches no credential.
# spoke-ci declares one optional secret (ATTIC_TOKEN); the cache-backed
# path reads the shared Bazel cache and does not upload, so it does not
# need one. Revisit only with a same-repo-only guard.

merge-gate:
name: merge-gate
if: always()
needs: [ci]
# TIN-3914 retired the GitHub-hosted class. `tinyland-nix` is the label
# the not-yet-applied `jesssullivan-blog-nix` scale set will carry, so this
# job has nowhere to run until that apply lands -- which is exactly the
# DO-NOT-MERGE condition on this change.
runs-on: tinyland-nix
timeout-minutes: 5
steps:
- name: Require complete reusable CI
env:
REUSABLE_CI_RESULT: ${{ needs.ci.result }}
run: test "$REUSABLE_CI_RESULT" = success
11 changes: 11 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ re-read immediately before their credentialed mutation.
| Shadow source publish (GHCR) | `.github/workflows/shadow-source-publish-v2.yml` | `workflow_run` consumer of `Build shadow source v2`; runs default-branch code only and independently revalidates provenance, never executing PR code | repo var `BLOG_SHADOW_SOURCE_PUBLISH_ENABLED` (default false), revalidated at package-write time |
| Private CV consistency | `.github/workflows/private-cv-authority-v2.yml` | exact current-`main` push + typed dispatch (`private-cv-verify-v2`) | none; credentialed verify-only lane that never commits or publishes, and is itself a required proof for production publish |
| Production health monitor | `.github/workflows/production-health-v2.yml` | cron health check every 30 minutes (ntfy alert on failure) + typed dispatch (`production-health-v2`, optional ntfy smoke) | none; notification credentials carry no serving-state mutation authority, and a red scheduled run is production evidence |
| Org spoke CI (TIN-3914, not yet servable) | `.github/workflows/spoke-ci.yml` | push to `main` + PR to `main`, calling `tinyland-inc/ci-templates/.github/workflows/spoke-ci.yml` pinned at the `v3.1.0` commit | none needed; passes no secrets, and every job targets the `jesssullivan-nix` capability class that no scale set serves for this repo yet |

- This repo owns blog source, the static build, shadow source-image
publication to `ghcr.io/jesssullivan/jesssullivan-github-io-shadow-tailnet`,
Expand All @@ -57,6 +58,16 @@ re-read immediately before their credentialed mutation.
- `tinyland-inc/GloriousFlywheel` supplies runner, Nix/toolchain, Bazel
cache/RBE, and validation substrate. Passing GF checks or running on GF
runners transfers no application deployment ownership.
- `tinyland-inc/ci-templates` owns the reusable spoke CI contract. TIN-3914
exception, recorded 2026-08-28: this repo's hand-rolled workflows pin
`runs-on: ubuntu-latest` at 17 sites, and `.github/workflows/spoke-ci.yml`
is the wiring that retires them, not proof they are retired. It is inert
until `Jesssullivan/jesssullivan-infra` applies a `jesssullivan-blog-nix`
ARC scale set serving the `jesssullivan-nix` label
(`tofu/stacks/arc-runners/jesssullivan.tfvars`), so `ci.yml` stays the
required-check authority and nothing about merge protection moves. Do not
hand-migrate individual `runs-on` lines or retire any `ci.yml` job ahead of
that apply: the tfvars entry lands first, the label flip second.
- `tinyland-inc/tinyland.dev` owns the mothership content, broker, and
federation contracts this spoke consumes.
- The `substrate-boundary` job in `.github/workflows/ci.yml` enforces that
Expand Down
56 changes: 56 additions & 0 deletions tinyland.repo.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
{
"$schema": "https://raw.githubusercontent.com/tinyland-inc/site.scaffold/main/docs/schemas/tinyland-repo-manifest.schema.json",
"schema_version": 1,
"repo": {
"name": "jesssullivan.github.io",
"github": "Jesssullivan/jesssullivan.github.io",
"domain": "transscendsurvival.org",
"description": "Personal static SvelteKit blog and CV spoke, published to Cloudflare Pages at transscendsurvival.org.",
"linear": {
"issue": "TIN-3914"
}
},
"taxonomy": {
"primary_role": "static-spoke",
"spawned_repo_role": "static-spoke",
"layers": ["org-wide-repo-contract", "bazel-package-cache-rbe", "static-spoke"]
},
"enrollment": {
"forgeScope": "Jesssullivan",
"operatorOverlay": "jesssullivan-infra",
"executionPool": "tinyland-nix",
"substrateMode": "shared-cache-backed"
},
"contracts": {
"agent_contract": "AGENTS.md",
"just": "Justfile",
"nix": "devshell-via-spoke-ci",
"github_actions": ".github/workflows",
"secrets_scan": "gitleaks",
"conformance": "just check"
},
"boundaries": {
"owns_runtime_backend": false,
"owns_auth": false,
"owns_payments": false,
"owns_activitypub_delivery": false,
"owns_live_broker_fetch": false,
"owns_static_projection_ingest": true,
"owns_gitops_apply": false,
"owns_cloudflare_mutation": false,
"owns_bazel_module_authority": false
},
"authorities": {
"content_authority": "tinyland-inc/tinyland.dev",
"ci_templates": "tinyland-inc/ci-templates",
"cache_rbe_authority": "tinyland-inc/GloriousFlywheel",
"package_registry": "tinyland-inc/bazel-registry"
},
"supply_chain": {
"sbom": {
"status": "planned",
"formats": ["CycloneDX JSON", "SPDX JSON"],
"notes": "No SBOM recipe exists in this repo yet. Adopting one is downstream of the spoke-ci adoption tracked in TIN-3914; status moves off planned only when a recipe lands."
}
}
}
Loading