π¦«ποΈ dispatch to foreman
π§ task enqueued
ββ priority = ?
ββ yieldage = ?
ββ leverage = ?
title
feat(org): declare GitHub org security lockdown β actions policy, workflow token defaults, fork-PR policy, 2FA
description
.what
ehmpathy/declastruct-aws needs to declare an org-level GitHub lockdown policy, and
four of the required resources do not exist in this package yet. this task asks for the
domain objects + DAOs + acceptance that make the whole policy declarable.
audit run against the live ehmpathy org on 2026-08-02 (read-only, via gh api -X GET).
.why
ehmpathy/declastruct-aws is a PUBLIC repo that provisions live AWS accounts. its
ehmpathy-demo-oidc role carries demoPermissionsPolicy (ec2:*, iam:*Role, budgets:*,
ce:*) and its trust policy uses StringLike on repo:ehmpathy/*:* β so any repo, any
branch, any workflow in the org can assume it.
that AWS-side hole gets fixed in declastruct-aws. but the GitHub-side controls that bound the
same blast radius are ALSO wide open, and today they can only be clicked, not declared:
| live setting |
value |
why it matters |
default_repository_permission |
write |
every member holds write on every repo -> can push a branch anywhere -> can assume the AWS role |
two_factor_requirement_enabled |
false |
one phished member = org write = the AWS role |
default_workflow_permissions |
write |
GITHUB_TOKEN is read-write by default across the org |
can_approve_pull_request_reviews |
true |
a bot token can approve a PR (OWASP CICD-SEC-1) |
allowed_actions |
all |
any third-party action, from anywhere, in any workflow |
sha_pinning_required |
false |
tags are mutable pointers (OWASP CICD-SEC-3 / -4) |
a control that can only be clicked drifts silently and leaves no diff for a reviewer. these
belong in a declared wish like every other resource.
.what already exists here (verified, no work needed)
DeclaredGithubOrgMemberPrivileges already covers defaultRepositoryPermission,
membersCanCreateRepositories, membersCanDeleteRepositories,
membersCanChangeRepoVisibility, membersCanForkPrivateRepositories,
membersCanInviteOutsideCollaborators
DeclaredGithubBranchProtection, DeclaredGithubOrgRuleset, DeclaredGithubRepoRuleset
DeclaredGithubOrg READS twoFactorRequirementEnabled
.the gaps β 4 asks
1. DeclaredGithubOrgActionsPermissions
GET/PUT /orgs/{org}/actions/permissions
enabledRepositories: all | none | selected
allowedActions: all | local_only | selected
shaPinningRequired: boolean
- and the companion
GET/PUT /orgs/{org}/actions/permissions/selected-actions
(githubOwnedAllowed, verifiedAllowed, patternsAllowed)
shaPinningRequired is the highest-value single field in this whole task β it enforces
rule.forbid.insecure.via=unpinned-third-party-code for every repo at once.
2. DeclaredGithubOrgActionsWorkflowDefaults
GET/PUT /orgs/{org}/actions/permissions/workflow
defaultWorkflowPermissions: read | write
canApprovePullRequestReviews: boolean
3. DeclaredGithubOrgActionsForkPrPolicy
GET/PUT /orgs/{org}/actions/permissions/fork-pr-workflows (and the repo-level peer)
- the approval-required policy for fork PRs, plus whether a fork PR may read secrets or hold
a write token
this is the one that lets outside contributors fork and contribute WITHOUT our resources,
which is exactly the posture we want β but it must be declared, not assumed.
4. twoFactorRequirementEnabled -> settable
it is readonly on DeclaredGithubOrg today. make it declarable, either by a move to
DeclaredGithubOrgMemberPrivileges or as its own resource. note it may need a plan-time
preflight: GitHub removes members who lack 2FA when it is turned on, so a set should
surface who would be dropped.
.acceptance
each of the four owes the full four, per
rule.require.dao-and-acceptance-per-declared-resource:
- a domain object with
unique keyed on the org
- a DAO via
genDeclastructDao
- provider registration (type map + factory) and sdk export
- acceptance coverage: plan-inclusion + post-apply
KEEP
plus:
- name them symmetric with the extant
DeclaredGithubOrg* peers
(rule.require.symmetry-with-peer-resources)
- secure defaults where a default is shipped β a consumer who declares one of these
without thought should land in the pit of success, not on GitHub\x27s permissive default
set must be idempotent (these are all PUT-shaped, so upsert is natural)
.the desired end state, for reference
DeclaredGithubOrgActionsPermissions.as({
org, enabledRepositories: "all",
allowedActions: "selected", shaPinningRequired: true,
});
DeclaredGithubOrgActionsWorkflowDefaults.as({
org, defaultWorkflowPermissions: "read", canApprovePullRequestReviews: false,
});
.sources
filed by beaver on behalf of vlad, out of the ehmpathy-camp grove behavior in
ehmpathy/declastruct-aws
π¦«ποΈ dispatch to foreman
title
feat(org): declare GitHub org security lockdown β actions policy, workflow token defaults, fork-PR policy, 2FA
description
.what
ehmpathy/declastruct-awsneeds to declare an org-level GitHub lockdown policy, andfour of the required resources do not exist in this package yet. this task asks for the
domain objects + DAOs + acceptance that make the whole policy declarable.
audit run against the live
ehmpathyorg on 2026-08-02 (read-only, viagh api -X GET)..why
ehmpathy/declastruct-awsis a PUBLIC repo that provisions live AWS accounts. itsehmpathy-demo-oidcrole carriesdemoPermissionsPolicy(ec2:*,iam:*Role,budgets:*,ce:*) and its trust policy usesStringLikeonrepo:ehmpathy/*:*β so any repo, anybranch, any workflow in the org can assume it.
that AWS-side hole gets fixed in declastruct-aws. but the GitHub-side controls that bound the
same blast radius are ALSO wide open, and today they can only be clicked, not declared:
default_repository_permissionwritetwo_factor_requirement_enabledfalsedefault_workflow_permissionswriteGITHUB_TOKENis read-write by default across the orgcan_approve_pull_request_reviewstrueallowed_actionsallsha_pinning_requiredfalsea control that can only be clicked drifts silently and leaves no diff for a reviewer. these
belong in a declared wish like every other resource.
.what already exists here (verified, no work needed)
DeclaredGithubOrgMemberPrivilegesalready coversdefaultRepositoryPermission,membersCanCreateRepositories,membersCanDeleteRepositories,membersCanChangeRepoVisibility,membersCanForkPrivateRepositories,membersCanInviteOutsideCollaboratorsDeclaredGithubBranchProtection,DeclaredGithubOrgRuleset,DeclaredGithubRepoRulesetDeclaredGithubOrgREADStwoFactorRequirementEnabled.the gaps β 4 asks
1.
DeclaredGithubOrgActionsPermissionsGET/PUT /orgs/{org}/actions/permissionsenabledRepositories:all | none | selectedallowedActions:all | local_only | selectedshaPinningRequired: booleanGET/PUT /orgs/{org}/actions/permissions/selected-actions(
githubOwnedAllowed,verifiedAllowed,patternsAllowed)shaPinningRequiredis the highest-value single field in this whole task β it enforcesrule.forbid.insecure.via=unpinned-third-party-codefor every repo at once.2.
DeclaredGithubOrgActionsWorkflowDefaultsGET/PUT /orgs/{org}/actions/permissions/workflowdefaultWorkflowPermissions:read | writecanApprovePullRequestReviews: boolean3.
DeclaredGithubOrgActionsForkPrPolicyGET/PUT /orgs/{org}/actions/permissions/fork-pr-workflows(and the repo-level peer)a write token
this is the one that lets outside contributors fork and contribute WITHOUT our resources,
which is exactly the posture we want β but it must be declared, not assumed.
4.
twoFactorRequirementEnabled-> settableit is
readonlyonDeclaredGithubOrgtoday. make it declarable, either by a move toDeclaredGithubOrgMemberPrivilegesor as its own resource. note it may need a plan-timepreflight: GitHub removes members who lack 2FA when it is turned on, so a
setshouldsurface who would be dropped.
.acceptance
each of the four owes the full four, per
rule.require.dao-and-acceptance-per-declared-resource:uniquekeyed on the orggenDeclastructDaoKEEPplus:
DeclaredGithubOrg*peers(
rule.require.symmetry-with-peer-resources)without thought should land in the pit of success, not on GitHub
\x27s permissive defaultsetmust be idempotent (these are all PUT-shaped, so upsert is natural).the desired end state, for reference
.sources
declastruct-aws/.agent/repo=.this/role=any/briefs/catalog.security.insecure-patterns.mdfiled by beaver on behalf of vlad, out of the
ehmpathy-campgrove behavior inehmpathy/declastruct-aws