Task 02 (the whole runner) ended at 21:08 with no file and no commit: Ornith wrote the
implementation out in its reply (~700 lines), OpenCode compacted the session, and the model
then emitted a malformed tool call. It had also looked for the given test at a wrong path
("_files/…" relative to the plan: my ambiguity).
- 02-runner → 02-runner-core (types, Submit, Status, Touch, Cancel; no goroutines) and
03-runner-workers; the given test split to match (runner_core_test.go gains three tests:
queued storage, cancel while queued, Status never moves the lease); later tasks renumbered
04-09 and every cross-reference checked.
- Copy paths spelled from the repo root.
- guard.PreCheck (+ its test) is committed here by the owner: the old task 05 told the
implementer to edit internal/guard/, which AGENTS.md forbids. My contradiction.
- AGENTS.md rule 6: write code into files early, in small steps.
Both runner test files compile against a panic-only skeleton (the core file also alone) and
fail there on panic: todo.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
54 lines
1.5 KiB
Go
54 lines
1.5 KiB
Go
package guard
|
|
|
|
// P6 (owner, before the run): PreCheck is CheckURL without name resolution, for refusing a batch target at
|
|
// submit time.
|
|
|
|
import (
|
|
"context"
|
|
"net/netip"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestPreCheck(t *testing.T) {
|
|
g := &Guard{
|
|
AllowPrefixes: []netip.Prefix{netip.MustParsePrefix("127.0.0.0/8")},
|
|
LookupIP: func(context.Context, string) ([]netip.Addr, error) {
|
|
t.Fatal("PreCheck resolved a name")
|
|
return nil, nil
|
|
},
|
|
}
|
|
for _, u := range []string{
|
|
"https://example.com/",
|
|
"http://example.com/path?q=1",
|
|
"https://internal.test/", // a name: not resolved here, so not refused here
|
|
"http://127.0.0.1:8080/", // an allowed literal is exempt from the port rule, as in CheckURL
|
|
"http://93.184.215.14/", // a public literal
|
|
"http://0x7f000001:8080/", // inet_aton form of 127.0.0.1: an allowed literal
|
|
} {
|
|
if err := g.PreCheck(u); err != nil {
|
|
t.Errorf("PreCheck(%q) = %v, want nil", u, err)
|
|
}
|
|
}
|
|
for _, u := range []string{
|
|
"",
|
|
"ftp://example.com/",
|
|
"http://user@example.com/",
|
|
"http://example.com:8080/",
|
|
"http://10.0.0.5/",
|
|
"http://169.254.169.254/latest/meta-data/",
|
|
"http://[::1]/",
|
|
"http://0x0a000005/", // inet_aton form of 10.0.0.5
|
|
} {
|
|
err := g.PreCheck(u)
|
|
if err == nil || !strings.HasPrefix(err.Error(), "blocked") {
|
|
t.Errorf("PreCheck(%q) = %v, want a blocked error", u, err)
|
|
}
|
|
}
|
|
// With no allow list, loopback is refused like any other private literal.
|
|
var zero Guard
|
|
if err := zero.PreCheck("http://127.0.0.1/"); err == nil {
|
|
t.Error("a zero Guard allowed loopback")
|
|
}
|
|
}
|