HCW field application standard¶
Version 1.0, drafted 2026-10-25 for ticket PF-2 (#255). It is the one shared rulebook for the four field application repositories, and the place that records, in the open, where a repository follows it and where it does not yet.
The four repositories (each is the upstream "App" of a product; the web-front "AddOn" editions are covered by the AddOn integration standard and are out of scope here):
| Short name | Repository | Default branch head read on 2026-10-25 |
|---|---|---|
| NE | HCW-NetworkEyes_App | 940cbb6e |
| CC | HCW-CloudCrawler_App | fa1f38a5 |
| CA | HCW-CloudAssessor_App | 190052bf |
| MO | HCW-MigrateOrchestrator_App | 2d90dd0 |
This page is accurate only as of the commits above. The repositories change every day (CloudAssessor gained its contributing files, issue forms and release guard on the day this page was written), so re-read a row before relying on it.
1. How to read this page¶
- MUST means every repository does it, or has a written exception in section 6. SHOULD means every repository does it unless it has a reason, and a missing one becomes a ticket. MAY is a choice the repository owns.
- Every statement about a repository was read from its default branch, the GitHub settings API or a workflow dry run on 2026-10-25. Nothing here was taken from memory. Where a fact could not be checked, the page says so (see section 9).
- The comparison starts from the table in
pull request #289
(merged 2026-10-25) and re-reads every row. Where this page disagrees with
that table, this page is the newer reading: for example CloudAssessor's
Dependabot now uses
uv(fixed after the ticket was written), and CloudCrawler's Dependabot file lists onlygithub-actionsanduv. - Words used: a ruleset is a repository's merge rules; a SHA pin names
an action by its full commit hash instead of a movable tag; OIDC is a
short-lived login that a workflow exchanges for a credential, so no password
is stored; provenance is a signed statement of which workflow built an
artifact; an SBOM (software bill of materials) lists the components in
it; a digest is the exact content hash of an image; CodeQL is
GitHub's code scanner; Dependabot opens pull requests for outdated
dependencies; Trivy, hadolint and actionlint are scanners and
linters for images, Dockerfiles and workflows; a dry run prints what a
task would change without changing it; an ADR is an architecture
decision record; a composite action is a reusable bundle of workflow
steps kept in
.github/actions/. - The owner decides what is mandatory. Items marked Owner decision are proposals until the owner answers on PF-2.
2. Requirements¶
2.1 Identity¶
| ID | Level | Requirement | Evidence it can be done |
|---|---|---|---|
| ID-1 | MUST | A public repository named HCW-<Product>_App for the upstream App (the AddOn is HCW-<Product>_AddOn). The default branch is main. |
All four. MO was renamed from HCW-AzMigrateOrchestrator_App (noted in #289; this repository's CHANGELOG records that the App had already been renamed when the AddOn was renamed on 2026-10-24). |
| ID-2 | MUST | A one-sentence description that names the product and says it is the upstream engine or appliance. | All four have one. |
| ID-3 | SHOULD | Topics (five to eight) and a homepage that points at the product's page on hybridcloudworks.com. | CA has topics and a homepage that points at its product page. MO has topics and a homepage that is the site root. NE and CC have no topics, and CC has no homepage. |
| ID-4 | MUST | A LICENSE file, and a NOTICE file when third-party material is redistributed. The proposed default licence is MIT unless the owner decides otherwise. |
LICENSE in all four; MIT in CC, CA, MO and Apache-2.0 in NE; NOTICE in CA and MO only. Owner decision (E-1). |
| ID-5 | MUST | "Automatically delete head branches" is on, so merged branches do not pile up. | On in NE, CA, MO; off in CC. |
| ID-6 | SHOULD | The repository wiki is off. Documentation lives in the repository and in the umbrella documentation site (ADR 0027, which retired the wiki on 2026-09-06). Discussions stay off until an owner decision turns them on. (An ADR is an architecture decision record, see DOC-6.) | Wiki is off in NE and MO, on in CC and CA. CA's own rules name the wiki as a documentation home (E-4). |
2.2 Documentation¶
| ID | Level | Requirement | Evidence |
|---|---|---|---|
| DOC-1 | MUST | The README.md has these sections, in this order, using these words in the headings: what it is, Status, Quick start (the commands that work on a clean machine), Configuration (points at .env.example), Repository layout, Documentation, Contributing, security and licence. |
None of the four matches yet; see the README outlines in section 4. |
| DOC-2 | MUST | CHANGELOG.md follows Keep a Changelog: an ## [Unreleased] section on top, then ## [X.Y.Z] - YYYY-MM-DD sections. It records completed work only. |
NE, CC, CA follow it. MO's headings are ## 0.2.1 — 2026-10-04 (…) and ## Unreleased, and it does not mention the format. |
| DOC-3 | MUST | CLAUDE.md at the repository root, with the section "How to communicate with the owner" (plain words, numbered steps for the owner, links to what is named). |
All four have it (NE, CC, CA, MO). |
| DOC-4 | MUST | The repository's documentation model (which markdown files may exist and where) is written down in CLAUDE.md or the README. |
NE (seven root documents), CA (five root documents) and MO (docs/ tree) state it. CC states it only through its ADR folder. |
| DOC-5 | SHOULD | A script checks the documentation model in CI. | NE (validate_documentation_model.py) and CA (scripts/check-docs-governance.py) have one. CC and MO have none found. |
| DOC-6 | SHOULD | Material design choices are recorded as ADRs (architecture decision records) in docs/adr/. Repositories whose model allows no docs/ folder keep decisions in REVIEW.md or TODO.md instead. |
CC (docs/adr/) and MO (docs/adr/, the canonical ADR log for both of its repositories) follow it; NE and CA use the exception. |
| DOC-7 | MAY | A GitHub Pages site. No repository publishes one today; the open tickets are CC-5 #11, NE-8 #247, CA-9 #32 and AMO-13 #54. Until one exists, the board view "GitHub Pages" stays empty. | None publish Pages. |
2.3 Community and contribution files¶
GitHub finds these files at the root, in docs/ or in .github/. New files go
in .github/; a file that already sits at the root stays there.
| ID | Level | Requirement | Evidence |
|---|---|---|---|
| COM-1 | MUST | SECURITY.md that tells reporters how to report privately (GitHub's private vulnerability reporting, optionally with an e-mail address), and private vulnerability reporting switched on. |
File in all four; setting enabled: true in all four. |
| COM-2 | MUST | CONTRIBUTING.md. |
All four. CA added it on 2026-10-25 (commit 190052bf). |
| COM-3 | MUST | CODE_OF_CONDUCT.md. |
All four. CA added it on 2026-10-25 (commit 190052bf). |
| COM-4 | SHOULD | SUPPORT.md that says where to ask a question. |
None of the four has one (G-13). |
| COM-5 | MUST | .github/CODEOWNERS. |
All four. |
| COM-6 | MUST | A pull request template with at least these sections: Summary, Verification (exact commands, and what was not run), Security and data. | All four have a template. MO's has Summary, Verification, Rules, Infrastructure and AI provenance, with no security section (G-1). |
| COM-7 | MUST | Issue forms (YAML) for a bug, a feature request and a work item, plus config.yml with blank issues turned off and security reports routed to the private form. |
NE: 3 forms (bug, feature, work item) and config. CA: the same, since 2026-10-25. CC: forms for bug, feature, ADR and FinOps finding, a markdown infrastructure_change.md, config, and no work-item form. MO: 2 forms (bug, feature), the markdown rule-change.md, no work-item form and no config.yml. |
2.4 Labels, issues and the board¶
| ID | Level | Requirement | Evidence |
|---|---|---|---|
| LAB-1 | MUST | These labels exist in every repository: P0, P1, P2, P3; severity:critical, severity:high, severity:medium, severity:low; workstream:ci, workstream:dependencies, workstream:docs, workstream:governance, workstream:pages, workstream:release, workstream:security, workstream:testing; product:networkeyes, product:cloudcrawler, product:cloudassessor, product:azmigrate (one per repository); needs-owner-decision. Each label maps to exactly one board option (P0 is "P0 Critical", workstream:docs is "Presentation and Documentation"); the mapping is in the board-fill task. |
No repository has the full set. Missing: NE P0, severity:critical, workstream:pages; CC P0, severity:critical; CA P0, severity:critical, workstream:pages; MO P0, P1, severity:critical, severity:high, workstream:dependencies, workstream:pages (G-3). |
| LAB-2 | MUST | Every issue carries one priority, one severity, one workstream and one product label. | 54 of the 84 board items had all four fields filled from labels on the morning of 2026-10-25. The other 30 had no labels and are listed in G-3. |
| LAB-3 | MUST | The board HCW Field Applications is public, has auto-add on (turned on by the owner on 2026-10-24, per PF-3), and has the fields, options and views in section 3. | Verified on 2026-10-25; see section 3. |
| LAB-4 | MUST | Board values are filled from labels by the board-fill task of the repository-admin workflow (NE file), not by hand. Issue forms use the board's own option lists, and a test in NE keeps them equal. |
Task exists and ran on 2026-10-25. |
2.5 Branch and tag protection¶
| ID | Level | Requirement | Evidence |
|---|---|---|---|
| PRO-1 | MUST | Two active rulesets: Protect main (no deletion, no force push, pull request required with 0 approvals, required status checks, repository admins may bypass only through a pull request) and Protect release tags (refs/tags/v* cannot be deleted, moved or updated, no bypass). |
Identical rules in all four, read through the rulesets API on 2026-10-25. |
| PRO-2 | MUST | The required checks include at least: lint, tests, secret scan and the image build. | See the required-checks table in section 4. NE requires no image build (Docker Build Smoke Test is not required) and no code-scanning check (G-6). MO requires appliance-image but no lint or dependency audit job. |
| PRO-3 | MUST | Rulesets change only through the repository-admin workflow (a dry run first, then apply), and the check list in that workflow equals the live ruleset. |
CC, CA, MO match. NE does not: the workflow lists 7 checks and the live ruleset has 10, so protect-main with apply would remove Dockerfile Lint (hadolint), Workflow Lint (actionlint) and Dependency Review (G-2). Observed: the dry run 40203506783 prints a payload with the 7 checks. Inferred from the workflow code: the task replaces the live ruleset with that payload (PUT), so the 3 newer checks would be removed. |
| PRO-4 | SHOULD | Every tag pattern that a release uses is covered by the tag ruleset. | NE also has the tag engine-v0.1.0, which refs/tags/v* does not cover (G-4). |
| PRO-5 | MUST | The default Actions token is read-only and Actions cannot approve pull requests. | read and false in all four. |
| PRO-6 | SHOULD | The Actions setting "Require actions to be pinned to a full-length commit SHA" is on. | Off in all four, although every uses: is already pinned (G-9). |
2.6 Pull requests and automation¶
| ID | Level | Requirement | Evidence |
|---|---|---|---|
| AUT-1 | MUST | The composite action .github/actions/self-merging-pr (NE copy) is present and has the same content in every repository. It opens a pull request with a short-lived GitHub App token so that required checks run, and turns on squash auto-merge. |
Byte-identical in all four on 2026-10-25 (the same git blob eccfa960, 6741 bytes, read through the contents API). |
| AUT-2 | MUST | A rehearsal that proves the action end to end without a real change: rehearse-self-merging-pr.yml. |
CC, CA, MO have the workflow. NE has the rehearsal as the rehearsal input of workflow 200 (E-2). |
| AUT-3 | MUST | No CI-suppression marker (the bracketed skip words) in a commit message, pull request title or body. The action's own input text says why: it would skip the required checks too. | Stated in the action; not machine-checked. |
| AUT-4 | SHOULD | Commit subjects read type(scope): what changed, with types such as feat, fix, build, ci, docs, test, chore, refactor. |
The last 12 non-merge commits: NE and CC follow it; CA and MO mix it with plain sentences. |
2.7 Continuous integration¶
| ID | Level | Requirement | Evidence |
|---|---|---|---|
| CI-1 | MUST | Every uses: of a third-party action is pinned to a full 40-character commit SHA with the version in a trailing comment (# v4.6.0). Dependabot proposes the updates. |
70 of 70 (NE), 35 of 35 (CC), 43 of 43 (CA), 55 of 55 (MO) are SHA-pinned and carry a version comment. |
| CI-2 | MUST | Every workflow has a top-level permissions: block (contents: read unless it needs more); a job that needs more asks for it itself. |
All workflows in all four. |
| CI-3 | MUST | The minimum job set exists and runs on every pull request: lint, test, secret scan, dependency audit, image build (or build and pack for MO). CC, CA, MO name jobs with short lowercase ids (lint, test, secret-scan, pip-audit, image); NE uses display names (E-2). |
NE, CC and CA have the set. MO has no blocking dependency audit; its OSV scanner in scanners.yml is report only (G-6). |
| CI-4 | SHOULD | actions/checkout sets persist-credentials: false. |
12 of 12 (CC), 7 of 23 (NE), 4 of 17 (MO), 3 of 15 (CA) (G-8). |
| CI-5 | SHOULD | Every job sets timeout-minutes. |
27 of 28 (NE), 8 of 14 (CC), 7 of 18 (MO), 2 of 16 (CA) (G-8). |
| CI-6 | SHOULD | Workflows are linted with actionlint and Dockerfiles with hadolint, both pinned. |
NE: both (#289). MO: hadolint. CC and CA: neither (G-8). |
| CI-7 | MUST | The README's Quick start gives the same commands CI runs, so a laptop result predicts the CI result. | NE adds scripts/ci/local-container-checks.sh for the container checks. Not re-run for the others (see section 9). |
2.8 Dependencies¶
| ID | Level | Requirement | Evidence |
|---|---|---|---|
| DEP-1 | MUST | .github/dependabot.yml covers github-actions (directories / and /.github/actions/*) and every package ecosystem that has a manifest, weekly, with updates grouped. |
github-actions is in all four. Gaps: CC has a Dockerfile but no docker entry; MO has Terraform under infrastructure/terraform/appliance-azure but no terraform entry; NE has docker-compose.yml but no docker-compose entry; groups (one pull request per batch of updates) are missing for CA's github-actions, docker and terraform entries and for MO's docker and docker-compose entries (G-5). |
| DEP-2 | MUST | Lockfiles are committed (uv.lock, package-lock.json) and checked in CI. |
uv.lock in NE, CC, CA; package-lock.json in MO and in NE's web app; checks: NE has the "Python Lockfile Consistency" job; CC and CA have scripts/check-lockfiles.sh; MO has no named lockfile check (G-5). |
| DEP-3 | MUST | A dependency review job runs on pull requests. | All four. Required by the ruleset only in NE (G-6). |
2.9 Security scanning¶
| ID | Level | Requirement | Evidence |
|---|---|---|---|
| SEC-1 | MUST | GitHub secret scanning and push protection are on. | On in all four. Validity checks and non-provider patterns are off in all four (G-10). |
| SEC-2 | MUST | A secret scan runs in CI (gitleaks; NE also runs detect-secrets as the gating scan). | All four. |
| SEC-3 | MUST | CodeQL covers every language in the repository (Python, JavaScript and TypeScript, and actions for the workflows). Prefer an advanced workflow with a config file, so the check has a stable name that a ruleset can require. |
NE's default setup scans only actions; its roughly 276 Python and 141 TypeScript and JavaScript files are not scanned (G-16). CC scans actions and Python. CA scans Python and JavaScript/TypeScript but not actions. MO scans JavaScript/TypeScript and actions; its 2 Python files are not scanned. Required by the ruleset only in MO (G-6). |
| SEC-4 | SHOULD | Every image to be published is scanned (Trivy or Docker Scout) before it is pushed. | Configured in CA (Trivy in publish-images.yml), MO (Trivy), NE (Docker Scout in workflow 200, plus a local Trivy script). CC builds an image in CI but does not scan it (G-7). |
| SEC-5 | MUST | Everything published carries a software bill of materials (SBOM) and build provenance. | Configured in the workflows: NE (SBOM, provenance and cosign signature in workflow 200); CC (CycloneDX SBOM and attestation for the wheel); CA and MO (sbom: true, provenance: true, attest-build-provenance). No container image has been published yet (see IMG-1), so this has not been observed on a real release. |
| SEC-6 | MAY | OpenSSF Scorecard and OSV scanner as report-only jobs. | MO only (scanners.yml). |
2.10 Releases¶
| ID | Level | Requirement | Evidence |
|---|---|---|---|
| REL-1 | MUST | Versions are plain X.Y.Z; release tags are vX.Y.Z; a GitHub Release is created from a tag, with the notes taken from the matching CHANGELOG.md section. |
Tags follow it in CA and MO. NE has v0.8.0, v0.1.0 and also engine-v0.1.0. CC has no tag yet (first release in preparation). Notes: all four MO releases have empty notes, and MO's changelog keeps its 0.3.1 entry under Unreleased; CA's two releases hold only the line "See CHANGELOG.md for v0.2.1." (G-4). Milestones are not used anywhere (0 in all four) and stay a MAY. |
| REL-2 | MUST | A release guard runs on every pull request and again on the tag: all version strings agree, the tag equals the version, the changelog has a dated section, and only commits on main are released. The reference is scripts/check-release-version.py with its --rehearse dry run. |
CC has the full guard. CA added scripts/check-release-version.py on 2026-10-25 (run in ci.yml and publish-core.yml; its content was not compared with CC's copy). NE (320-release-engine.yml, engine-v tags) and MO (release-cli.yml) check the tag against the package version at tag time only, not on pull requests, and do not check the changelog or that the commit is on main (G-4). |
| REL-3 | MUST | Publishing uses OIDC or trusted publishing. No registry password or token is stored in the repository's secrets. | CC (PyPI trusted publishing), CA and MO (Docker Hub OIDC connection), NE workflow 200 (OIDC). Exception: NE workflow 370 uses the stored DOCKERHUB_PERSONAL_TOKEN (tracked as R-026 step 3 in NE's REVIEW.md). |
| REL-4 | MAY | .github/release.yml to group generated notes by label. |
CC only. |
2.11 Container images¶
An image that is meant to qualify for Docker's free open-source programme (DSOS) also follows the open-source Docker app dossier: thirteen checks (licence, copyright holder, how the image is published, wording, active development and more), each with how to check it, and a template that records the proof for a product.
| ID | Level | Requirement | Evidence |
|---|---|---|---|
| IMG-1 | MUST | Images to be published are named docker.io/hybridcloudworks/img-<short>-<job>-<type>, for example img-ne-appliance-app, img-ca-appliance-app, img-mo-appliance-app. <short> is the product's two-letter code, <job> is what the image does (appliance, lab), <type> is app or addon. The tag is the full release tag (v0.1.0). |
NE, CA and MO workflows are configured with this name, but nothing has been published: Docker Hub shows no tags for the three img-*-appliance-app repositories on 2026-10-25, DOCKERHUB_ENABLED is not set in CA or MO, and MO's changelog says the image was never published. CC publishes no image. The convention is recorded in this repository's CHANGELOG entry for the add-on images; it had no standards page until this one. |
| IMG-2 | MUST | Every FROM is pinned to a digest, and the final stage runs as a numeric non-root user. |
Digests: every FROM line in the 7 Dockerfiles of the four repositories. User: 1001 (NE), 10001 (CC, CA); MO uses the name node, which Kubernetes runAsNonRoot cannot verify (G-8). |
2.12 Configuration, secrets and variables¶
| ID | Level | Requirement | Evidence |
|---|---|---|---|
| CFG-1 | MUST | .env.example lists every environment variable with a comment and no real value. |
File present in all four; that it is complete was not checked. |
| CFG-2 | MUST | The GitHub App credentials are the variable APP_CLIENT_ID and the secret APP_PRIVATE_KEY, held in the admin-ops environment (main branch only). The one personal token allowed is PROJECT_TOKEN, because a personal-account Project (v2) cannot be reached with an App token. |
CC, CA, MO follow it. NE also reads GH_APP_ID and GH_APP_PRIVATE_KEY in the notify-appliances job of workflow 200 (G-11). |
2.13 Agent instructions¶
| ID | Level | Requirement | Evidence |
|---|---|---|---|
| AGT-1 | MUST | CLAUDE.md is the working agreement (DOC-3). |
All four. |
| AGT-2 | SHOULD | .github/copilot-instructions.md and AGENTS.md exist when the repository is worked on with those tools, and say the same as CLAUDE.md. |
MO has both; CC has copilot-instructions.md; NE and CA have neither. |
3. The project board¶
Board: HCW Field Applications (user project 7, public). It was brought to this specification on 2026-10-25 (ticket PF-3 (#256)).
| Item | Specification |
|---|---|
| Fields | Repository (built in), Product, Workstream, Status, Priority, Severity, Effort, Owner, Blocking Reason, Target Release, Validation Environment, Evidence, Last Reviewed. |
| Status | Intake, Triaged, Ready, In Progress, In Review, Blocked, Validation, Done, Accepted Risk, Not Applicable. New items arrive as Intake (the built-in "item added" workflow uses the first option). |
| Priority | P0 Critical, P1 High, P2 Medium, P3 Low. |
| Severity | Critical, High, Medium, Low. |
| Workstream | Presentation and Documentation, Security and Dependencies, Pull Requests and CI, Testing and Validation, GitHub Pages, Governance, Release. |
| Product | HCW NetworkEyes, Cloud Crawler, Cloud Assessor, Azure Migration Orchestrator, Portfolio. |
| Views (table layout) | Portfolio Overview is:open; Presentation and Documentation workstream:"Presentation and Documentation"; Security and Dependencies workstream:"Security and Dependencies"; Pull Requests and CI workstream:"Pull Requests and CI"; Testing and Validation workstream:"Testing and Validation"; GitHub Pages workstream:"GitHub Pages"; Blocked and Owner Decision Required label:"needs-owner-decision" is:open; Completed status:Done. |
The option lists for Product, Workstream, Priority, Severity, Effort and
Validation Environment live in the board-fields task of
390-repository-admin.yml and in NE's work_item.yml form. Change both
together; a NE test fails when they differ.
4. Evidence tables¶
Required checks in the "Protect main" ruleset (live, 2026-10-25)¶
| Repository | Required checks |
|---|---|
| NE | Lint & Format, Unit Tests (Python 3.14), Web lint, typecheck & tests, Python Lockfile Consistency, Python Dependency Audit (pip-audit), Secret Scanning (detect-secrets, gating), Repository Guardrails, Dockerfile Lint (hadolint), Workflow Lint (actionlint), Dependency Review |
| CC | lint, test, contract, pip-audit, secret-scan, image |
| CA | lint, test, boundary, catalog-check, secret-scan, image, terraform |
| MO | build-test, codeql, secret-scan, packed-consumer, generated-terraform, appliance-image |
README outlines (second-level headings, as found)¶
| Repository | Headings |
|---|---|
| NE | Documentation map; Repository layout; Repository topology; Quick start; Configuration; Repository conventions |
| CC | What it does; Is there a user interface?; Status; Getting started; Signing in with Microsoft Entra; Releasing the engine; Repository layout; Rules that do not bend; Branch and tag protection; Repository standards; Contributing, security, license |
| CA | Project status; Overview; Repository layout; Quick start; Installation; Configuration; Documentation; Repository conventions |
| MO | The two repositories; Quick start; Repository map; Releases and artifacts; Principles baked into code; Contributing, security, license |
Other repository facts¶
| Item | NE | CC | CA | MO |
|---|---|---|---|---|
| Licence | Apache-2.0 | MIT | MIT | MIT |
| Workflows | numbered 200..390 (6) |
descriptive (7) | descriptive (7) | descriptive (11) |
| Dependabot ecosystems | uv, github-actions, docker (4 dirs), npm | github-actions, uv | uv, github-actions, docker, terraform | npm, github-actions, docker, docker-compose |
| CodeQL | default setup | workflow codeql.yml |
job in security.yml |
job in security.yml |
| Wiki | off | on | on | off |
| Auto-delete branches | on | off | on | on |
| Topics | none | none | 6 | 8 |
5. Conformance of each repository to the MUST items¶
"Yes" means observed. "Cfg" means configured in a workflow but not yet seen on a real release. "Part" means partly, with the gap number from section 7. "E-n" means a written exception in section 6. "Not checked" is listed in section 9.
| ID | NE | CC | CA | MO |
|---|---|---|---|---|
| ID-1 name, ID-2 description | Yes | Yes | Yes | Yes |
| ID-4 licence | Yes, E-1 | Yes | Yes | Yes |
| ID-5 delete merged branches | Yes | No (G-12) | Yes | Yes |
| DOC-1 README outline | Part (G-14) | Part (G-14) | Part (G-14) | Part (G-14) |
| DOC-2 changelog format | Yes | Yes | Yes | Part (G-14) |
DOC-3 / AGT-1 CLAUDE.md |
Yes | Yes | Yes | Yes |
| DOC-4 documentation model written | Yes | Part (G-14) | Yes | Yes |
| COM-1 security policy and private reporting | Yes | Yes | Yes | Yes |
| COM-2 CONTRIBUTING | Yes | Yes | Yes | Yes |
| COM-3 CODE_OF_CONDUCT | Yes | Yes | Yes | Yes |
| COM-5 CODEOWNERS | Yes | Yes | Yes | Yes |
| COM-6 pull request template | Yes | Yes | Yes | Part (G-1) |
COM-7 issue forms and config.yml |
Yes | Part (G-1) | Yes | Part (G-1) |
| LAB-1 label set | Part (G-3) | Part (G-3) | Part (G-3) | Part (G-3) |
| LAB-2 labels on every issue | Part (G-3) | Yes | Part (G-3) | Part (G-3) |
| LAB-3 / LAB-4 board | Yes | Yes | Yes | Yes |
| PRO-1 two rulesets | Yes | Yes | Yes | Yes |
| PRO-2 required checks cover lint, test, secret scan, image | Part (G-6) | Yes | Yes | Part (G-6) |
| PRO-3 admin workflow equals live ruleset | No (G-2) | Yes | Yes | Yes |
| PRO-5 read-only token | Yes | Yes | Yes | Yes |
| AUT-1 self-merging action | Yes | Yes | Yes | Yes |
| AUT-2 rehearsal | E-2 | Yes | Yes | Yes |
| AUT-3 no CI-suppression markers | Not checked | Not checked | Not checked | Not checked |
| CI-1 pinned with version comment | Yes | Yes | Yes | Yes |
| CI-2 top-level permissions | Yes | Yes | Yes | Yes |
| CI-3 minimum job set | Yes, E-2 | Yes | Yes | Part (G-6) |
| CI-7 README commands equal CI | Not checked | Not checked | Not checked | Not checked |
| DEP-1 Dependabot covers every ecosystem | Part (G-5) | Part (G-5) | Part (G-5) | Part (G-5) |
| DEP-2 lockfiles checked | Yes | Yes | Yes | Part (G-5) |
| DEP-3 dependency review job | Yes | Yes | Yes | Yes |
| SEC-1 secret scanning and push protection | Yes | Yes | Yes | Yes |
| SEC-2 CI secret scan | Yes | Yes | Yes | Yes |
| SEC-3 CodeQL covers every language | No (G-16) | Yes | Part (G-16) | Yes |
| SEC-5 SBOM and provenance | Cfg | Cfg | Cfg | Cfg |
| REL-1 versions, tags and notes | Part (G-4) | n/a (no release yet) | Part (G-4) | Part (G-4) |
| REL-2 release guard | Part (G-4) | Yes | Yes | Part (G-4) |
| REL-3 no stored registry credential | Part (G-11) | Yes | Yes | Yes |
| IMG-1 image name | Cfg | n/a (no image) | Cfg | Cfg |
| IMG-2 digest pins and numeric user | Yes | Yes | Yes | Part (G-8) |
CFG-1 .env.example |
Yes | Yes | Yes | Yes |
| CFG-2 credential names | Part (G-11) | Yes | Yes | Yes |
6. Exceptions¶
Only an exception with a reason and an owner counts as justified. A line with "Owner decision" is not yet justified.
| ID | Repository | What differs | Reason | Status |
|---|---|---|---|---|
| E-1 | NE | Licence is Apache-2.0, the others MIT. | No reason is written down in the repository. | Owner decision |
| E-2 | NE | Numbered workflows (200..390), job display names such as Lint & Format, and the rehearsal as an input of workflow 200 instead of its own file. |
NE's guardrail tests pin the workflow set and its bands (CLAUDE.md, "Workflows are numbered in bands"). Required-check names must stay as they are. |
Justified |
| E-3 | MO | Node and TypeScript instead of Python: no pip-audit, no uv, npm and package-lock.json instead. |
The product is a TypeScript monorepo. (The missing blocking dependency audit is not part of this exception; it is G-6.) | Justified |
| E-4 | CA | Documentation model allows five root documents and sends everything else to the GitHub Wiki (CLAUDE.md, "Documentation model"). |
Predates ADR 0027, which retired the wiki. | Owner decision (move to docs/ or keep the wiki) |
| E-5 | NE, CA | Community files only in .github/; no docs/ folder. |
The documentation models of both repositories allow only a few root documents. | Justified |
| E-6 | MO | The downstream web-front edition can never reach Azure: azure-auth, azure-arm and azure-execution are never published as packages (CLAUDE.md). |
Safety rule of the product. No standard item may weaken it, and publishing steps (REL-3) must keep those packages out of the publish list. | Justified |
| E-7 | CC | No image is published and no tag exists yet. | The first release (v0.1.0) is in preparation. |
Justified until the first tag |
7. Gaps and proposed tickets¶
None of these tickets exists yet. Each one carries the labels the standard asks
for (priority, severity, workstream, product) and belongs on the board. Where
the fix changes a ruleset or a setting, it goes through the repository-admin
workflow or is done by the owner in the browser.
| Gap | Proposed ticket | Labels | Done when |
|---|---|---|---|
| G-1 | Community files. CC: add a work-item issue form. MO: add .github/ISSUE_TEMPLATE/config.yml, a work-item form, turn rule-change.md into a form, and add a security section to the pull request template. (CA finished its part on 2026-10-25.) Split into one ticket per repository. |
P3, severity:low, workstream:governance, product:cloudcrawler / product:azmigrate | COM-6 and COM-7 read "Yes" for both. |
| G-2 | NE: update REQUIRED_CHECKS in 390-repository-admin.yml to the 10 live checks (plus any added by G-6), and add a test that fails when the list differs from the job names in workflow 300. |
P1, severity:high, workstream:governance, product:networkeyes | A dry run of protect-main prints the same check list as the live ruleset. |
| G-3 | All four: add the missing labels (LAB-1), keep them in one labels.json like CC's, and add the four labels to the issues that have none: NE #291, CA #1, CA #2, CA #3, CA #9, MO #21, and the 24 older closed issues (23 in NE, 1 in CA) that the pull request adding this page lists. The board already holds values for all of them, set by inference on 2026-10-25, so the board is complete; the labels are what is missing. |
P2, severity:medium, workstream:governance, product:portfolio | LAB-1 and LAB-2 read "Yes" in all four. |
| G-4 | Releases: add the full guard (check-release-version.py with its --rehearse mode, the changelog check and the "commit is on main" check) to NE and MO, and bring CA's copy in line with CC's; extend NE's tag ruleset to cover engine-v* or rename the tag family; fill the release notes from the changelog section for CA and MO and move MO's 0.3.1 entry out of Unreleased. |
P2, severity:medium, workstream:release, product:portfolio | REL-1, REL-2 and PRO-4 read "Yes". |
| G-5 | Dependabot: add docker to CC, terraform to MO, docker-compose to NE; add groups to CA (github-actions, docker, terraform) and MO (docker, docker-compose); give MO a named lockfile check. |
P3, severity:low, workstream:dependencies, product:portfolio | DEP-1 and DEP-2 read "Yes" in all four. |
| G-6 | Required checks, through the repository-admin workflow after each job has run once: require Dependency Review and the CodeQL check where they exist (CC, CA; MO already requires codeql and needs dependency-review); require Docker Build Smoke Test in NE; give MO a blocking lint job and a blocking npm dependency audit and require them. |
P2, severity:medium, workstream:security, product:portfolio | PRO-2, CI-3 and DEP-3 are enforced by the ruleset. |
| G-7 | CC: scan the image built in CI with Trivy (digest-pinned, as in CA). | P3, severity:low, workstream:security, product:cloudcrawler | SEC-4 reads "Yes". |
| G-8 | CI hygiene: set persist-credentials: false on every checkout and timeout-minutes on every job (counts in CI-4 and CI-5); add actionlint and hadolint to CC and CA; give MO's image a numeric user. |
P3, severity:low, workstream:ci, product:portfolio | CI-4, CI-5, CI-6, IMG-2 read "Yes". |
| G-9 | Owner: switch on "Require actions to be pinned to a full-length commit SHA" in the four repositories (NE, CC, CA, MO). All current uses: lines are pinned, so nothing should break. |
P2, severity:medium, workstream:security, product:portfolio | PRO-6 reads "Yes". |
| G-10 | Owner decision: secret scanning validity checks and non-provider patterns (off in all four). | P3, severity:low, workstream:security, product:portfolio | Decision recorded. |
| G-11 | NE: use APP_CLIENT_ID and APP_PRIVATE_KEY in the notify-appliances job instead of GH_APP_ID and GH_APP_PRIVATE_KEY and delete the two old secrets; decide the stored DOCKERHUB_PERSONAL_TOKEN used by workflow 370 (step 3 of R-026 in NE's REVIEW.md). |
P3, severity:low, workstream:security, product:networkeyes | CFG-2 and REL-3 read "Yes". |
| G-12 | CC: switch on "Automatically delete head branches" (settings page). | P3, severity:low, workstream:governance, product:cloudcrawler | ID-5 reads "Yes". |
| G-13 | SUPPORT.md in all four; topics and homepage for NE and CC; decide the wiki for CC and CA (ID-6, E-4); optional AGENTS.md and copilot-instructions.md for NE and CA. |
P3, severity:low, workstream:docs, product:portfolio | ID-3, ID-6, COM-4, AGT-2 read "Yes". |
| G-14 | README outline (DOC-1) in all four, Keep a Changelog headings in MO (DOC-2), a documentation model statement in CC (DOC-4), commit style (AUT-4) written into each CONTRIBUTING.md. |
P3, severity:low, workstream:docs, product:portfolio | DOC-1, DOC-2, DOC-4, AUT-4 read "Yes". |
| G-15 | Owner decision: licence of NE (E-1) and which repositories need a NOTICE. |
P3, severity:low, workstream:governance, product:portfolio | E-1 resolved. |
| G-16 | CodeQL coverage. NE: replace default setup (which scans only actions) with an advanced workflow for Python, JavaScript/TypeScript and actions, and require its check. CA: add actions. |
P2, severity:medium, workstream:security, product:portfolio | SEC-3 reads "Yes" in all four. |
8. Keeping this page true¶
- Owner: the repository owner decides the MUST list. A change to a MUST row
is an ADR-style entry in
CHANGELOG.mdof this repository, the repositories it affects each get a ticket, and the conformance table is updated in the same pull request. - Review cadence: re-read the four repositories every quarter, and after
any change to the
repository-adminworkflow, a ruleset or the board. Re-running the commands in section 9 reproduces every figure on this page. - Single copy: the page lives here, in the umbrella repository, because NE and CA allow almost no extra markdown and this repository already holds the other standards. The four READMEs should link here ("Repository conventions" in NE and CA, "Repository standards" in CC; part of G-14).
9. How the evidence was gathered, and what was not checked¶
Read-only, on 2026-10-25, with the gh command line signed in as the owner. An
independent reviewer (the cloud-documentation-archivist agent) re-checked a
sample of the figures against the repositories, and the errors it found were
corrected before this page was published. The sources were:
- Files and settings:
gh api repos/<owner>/<repo>,/git/trees/main?recursive=1,/rulesetsand/rulesets/<id>,/labels,/milestones,/releases,/tags,/private-vulnerability-reporting,/code-scanning/default-setup,/actions/permissionsand/actions/permissions/workflow. - Workflow contents,
dependabot.yml, composite action and Dockerfiles: read from each repository'sorigin/mainand parsed (counts ofuses:,persist-credentials,timeout-minutes, version comments). - The
repository-adminworkflow (NE run 40202353505, run 40202402877 and run 40203506783 were dry runs).
Not checked:
- Whether
.env.examplelists every variable the code reads (CFG-1). - Whether each README's Quick start commands still work (CI-7).
- Whether the commit-style reading (AUT-4) holds beyond the last 12 commits.
- That the issue forms render as intended on github.com.
- The AddOn repositories, and the umbrella repository's own conformance.
- Whether any pull request open in the four repositories changes a row above.
- Whether CA's new
check-release-version.pyis the same file as CC's. - Docker Hub was read as a public visitor (no tags on the three
img-*-appliance-apprepositories); a private tag would not show. - Branch-protection behaviour in practice: only the ruleset definitions were read, nothing was pushed to test them.