Skip to content
Merged
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
10 changes: 5 additions & 5 deletions .gds/bundle.lock.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ schema_version: 1
bundle:
version: "0.9.7-dev"
release_sequence: 0
source_tree_digest: "sha256:ba259a2260cfc55a79b76c69ea895ab446ea9ae6fe2892a016688713f903e162"
digest: "sha256:9b2dd4f5e413021932c2454c7e482fd790482ec9246e5adaf783dc92780672d9"
source_tree_digest: "sha256:ff0bdb5a3aecc647e785a571e5b08f4d47afdf4b9865139b63670f7636ed0df0"
digest: "sha256:83833e3c808531d699accaa7bde3e31289a631da93553c4fae5d08d9ffe902cd"

projection:
input_digest: "sha256:4145cec9f3f37a5c3930907936c97ebab0dd5d3e96a3ee480220aa32255c2ffe"
output_digest: "sha256:2572b8c1c82ccf29b5f7950c788f29cc5504bebf64b141e6b60b743d65366717"
input_digest: "sha256:847d847bf309749351054160ec089ef7f7d22a1969c26a3eb82ca69fa58beb23"
output_digest: "sha256:469c17732e4509ca38c6f2903b590cc0e8670502f965ebf50b4b40833e3f2cb4"
files:
- path: ".gds/compiled-policy.json"
digest: "sha256:9f498788bdc34e52a0ab793c536e0e6a7b360c2e1a20446cbf03ed51986cdc6f"
- path: ".github/workflows/gds-ci.yml"
digest: "sha256:439aac0176476d26063ff3799233a79a1032b905b737aa1b1db56d12f5c9b658"
digest: "sha256:75d8ce3e084bc5b3f1b33ce920b245d635915810cb97fb9887db0eba168d5f7a"
4 changes: 2 additions & 2 deletions .github/workflows/gds-ci.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# GENERATED FILE - DO NOT EDIT DIRECTLY
# generator: gds
# bundle: 0.9.7-dev
# source-tree-digest: sha256:ba259a2260cfc55a79b76c69ea895ab446ea9ae6fe2892a016688713f903e162
# input-digest: sha256:4145cec9f3f37a5c3930907936c97ebab0dd5d3e96a3ee480220aa32255c2ffe
# source-tree-digest: sha256:ff0bdb5a3aecc647e785a571e5b08f4d47afdf4b9865139b63670f7636ed0df0
# input-digest: sha256:847d847bf309749351054160ec089ef7f7d22a1969c26a3eb82ca69fa58beb23
# output-digest: sha256:4ef1ee2fcc42927eaedef9c85f7b421f87e5cc75ff7055ef520216a00f7d4b74
# edit-source:
# - .gds/repository.yaml
Expand Down
4 changes: 2 additions & 2 deletions core/app/projection_operations.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,10 +260,10 @@ func (services *Services) projectionOperationContext(
return projectionContext{}, []domain.Finding{dependencyFinding(path, infoErr)}
}
anchor, findings = manifest.NewLoader(services.Schemas).LoadRepository(repositoryInfo.WorktreeRoot)
if len(findings) == 0 && !isPublicModuleProjection(anchor) {
if len(findings) == 0 && anchor.Classification.VisibilityContract != "public" {
findings = []domain.Finding{{
Code: "GDS_PROJECTION_RELEASE_TARGET_INVALID", Severity: domain.SeverityHigh,
Message: "Released projection sources are accepted only for public modules.",
Message: "Released projection sources are accepted only for public repositories.",
}}
}
var releasedManifest bundle.Manifest
Expand Down
105 changes: 105 additions & 0 deletions core/app/released_project_projection_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package app

import (
"context"
"os"
"os/exec"
"path/filepath"
"strings"
"testing"
)

func TestReleasedPublicProjectRequiresArtifactWithoutFallingBackToEstate(t *testing.T) {
root := releasedProjectFixture(t, "public")
services, err := NewServices(DefaultClock)
if err != nil {
t.Fatal(err)
}
archive := filepath.Join(t.TempDir(), "missing-release.tar.gz")
_, findings := services.projectionOperationContext(context.Background(), root, ProjectionSourceOptions{
BundleArchive: archive, ReleaseEnvelope: archive + ".json",
})
if len(findings) != 1 || findings[0].Code != "GDS_LOCAL_OPERATION_NOT_PROVEN" ||
findings[0].Evidence["path"] != archive {
t.Fatalf("public project did not require its exact released artifact: %#v", findings)
}
if _, err := os.Stat(filepath.Join(root, ".gds", "compiled-policy.json")); !os.IsNotExist(err) {
t.Fatalf("artifact failure wrote a projection: %v", err)
}
}

func TestReleasedPrivateProjectCannotDetachFromEstatePolicy(t *testing.T) {
root := releasedProjectFixture(t, "private")
services, err := NewServices(DefaultClock)
if err != nil {
t.Fatal(err)
}
_, findings := services.projectionOperationContext(context.Background(), root, ProjectionSourceOptions{
BundleArchive: "untrusted.tar.gz", ReleaseEnvelope: "untrusted.json",
})
if len(findings) != 1 || findings[0].Code != "GDS_PROJECTION_RELEASE_TARGET_INVALID" {
t.Fatalf("private project could bypass canonical estate policy: %#v", findings)
}
}

func releasedProjectFixture(t *testing.T, visibility string) string {
t.Helper()
root := t.TempDir()
if err := os.Mkdir(filepath.Join(root, ".gds"), 0o755); err != nil {
t.Fatal(err)
}
anchor := `schema_version: 1
repository:
id: repo_01JEXAMPZ00000000000000001
display_name: example-project
roles: [project]
lifecycle: active
provider:
type: github
installation: installation:example
repository_id: 1234
owner: example-owner
name: example-project
classification:
portfolios: [portfolio:example]
visibility_contract: VISIBILITY
data_classification: VISIBILITY
policy:
profiles: [repository-default]
rollout_ring: standard
git:
default_branch: main
integration: pull-request
branch_model: task-branches
handoff_pr: preferred
cleanup: merged-only
verification:
commands:
test: [git diff --check]
required: [test]
agent:
context_profile: project-default
generated_agents: false
serena:
enabled: false
provenance_required: false
release:
mode: none
`
if err := os.WriteFile(filepath.Join(root, ".gds", "repository.yaml"),
[]byte(strings.ReplaceAll(anchor, "VISIBILITY", visibility)), 0o644); err != nil {
t.Fatal(err)
}
for _, args := range [][]string{
{"init", "--quiet", "--initial-branch=main"},
{"add", ".gds/repository.yaml"},
{"-c", "user.name=Example", "-c", "user.email=example@example.test", "-c", "commit.gpgsign=false",
"commit", "--quiet", "-m", "fixture"},
} {
command := exec.Command("git", append([]string{"-C", root}, args...)...)
if output, err := command.CombinedOutput(); err != nil {
t.Fatalf("fixture Git %v: %v: %s", args, err, output)
}
}
return root
}
3 changes: 2 additions & 1 deletion docs/contracts/cli-v1.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,8 @@ with leaf provenance. It does not write the compiled document.
### `gds generate repository`

`--bundle-archive` and `--release-envelope` select an immutable released
projection source for a standalone public module. They are an inseparable pair
projection source for a public repository, including a project without the
`module` role. They are an inseparable pair
and apply equally to candidate, check, plan, apply and verify modes. The command
never fetches a mutable URL and never treats an unverified extracted directory
as authority.
Expand Down
3 changes: 2 additions & 1 deletion docs/contracts/projections-v1.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ Development locks use sequence `0`. A released lock requires a positive
sequence and attestation identity digest. The development lock is test
evidence, not a released immutable bundle.

Standalone public modules consume released policy without copying its source
Public repositories, including ordinary projects and standalone modules,
consume released policy without copying its source
tree into every repository:

```bash
Expand Down
Loading