diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f53d642..2883b91 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -46,6 +46,9 @@ jobs: - name: Run Build run: go build ./... + - name: Verify SEO Metadata & Artifacts + run: python3 scripts/test_seo.py + frontend-ci: name: Frontend UI CI runs-on: ubuntu-latest diff --git a/.slop/ceilings.yml b/.slop/ceilings.yml index 3df9286..90144e8 100644 --- a/.slop/ceilings.yml +++ b/.slop/ceilings.yml @@ -3,4 +3,4 @@ scopes: go_production: active_clones_ceiling: 101 go_tests: - active_clones_ceiling: 314 + active_clones_ceiling: 313 diff --git a/cmd/dashboard/dogfood_api_test.go b/cmd/dashboard/dogfood_api_test.go index e67036e..b7dd1d2 100644 --- a/cmd/dashboard/dogfood_api_test.go +++ b/cmd/dashboard/dogfood_api_test.go @@ -45,14 +45,12 @@ func TestServeDogfoodActive_NullWhenNoneStarted(t *testing.T) { if rec.Code != http.StatusOK { t.Fatalf("status=%d body=%q", rec.Code, rec.Body.String()) } - var body struct { - Cohort *storage.DogfoodCohort `json:"cohort"` - } - if err := json.Unmarshal(rec.Body.Bytes(), &body); err != nil { + var payload map[string]json.RawMessage + if err := json.Unmarshal(rec.Body.Bytes(), &payload); err != nil { t.Fatal(err) } - if body.Cohort != nil { - t.Fatalf("expected a null cohort before any run starts, got %+v", body.Cohort) + if string(payload["cohort"]) != "null" { + t.Fatalf("expected a null cohort before any run starts, got %s", payload["cohort"]) } } @@ -82,23 +80,15 @@ func TestServeDogfoodStart_CreatesCohortThenConflictsOnASecondCall(t *testing.T) } } -func TestServeDogfoodFeedback_RequiresAJobID(t *testing.T) { - setupTestDB(t) - req := httptest.NewRequest(http.MethodPost, "/api/dogfood/feedback", bytes.NewBufferString(`{"category":"nothing"}`)) - rec := httptest.NewRecorder() - serveDogfoodFeedback(rec, req) - if rec.Code != http.StatusBadRequest { - t.Fatalf("status=%d, want 400", rec.Code) - } -} - -func TestServeDogfoodFeedback_RejectsUnknownCategory(t *testing.T) { +func TestServeDogfoodFeedback_RejectsInvalidPayloads(t *testing.T) { setupTestDB(t) - req := httptest.NewRequest(http.MethodPost, "/api/dogfood/feedback", bytes.NewBufferString(`{"job_id":"1","category":"not_a_real_category"}`)) - rec := httptest.NewRecorder() - serveDogfoodFeedback(rec, req) - if rec.Code != http.StatusBadRequest { - t.Fatalf("status=%d, want 400", rec.Code) + for _, payload := range []string{`{"category":"nothing"}`, `{"job_id":"1","category":"not_a_real_category"}`} { + req := httptest.NewRequest(http.MethodPost, "/api/dogfood/feedback", bytes.NewBufferString(payload)) + rec := httptest.NewRecorder() + serveDogfoodFeedback(rec, req) + if rec.Code != http.StatusBadRequest { + t.Fatalf("payload %q: status=%d, want 400", payload, rec.Code) + } } } @@ -121,6 +111,20 @@ func TestServeDogfoodReport_NullWhenNoCohortsExist(t *testing.T) { } } +func seedTestDogfoodJob(t *testing.T, id int, ts time.Time) { + t.Helper() + u := "https://boards.greenhouse.io/example/jobs/dogfood-" + string(rune('0'+id)) + _, err := db.Exec(` + INSERT INTO job_funnel (id, company_name, job_title, status, url, discovered_at) + VALUES (?, 'Company', 'Engineer', 'AWAITING_REVIEW', ?, ?); + INSERT INTO assisted_applications (job_id, original_status, next_action_code, assisted_state, revalidation_state, revalidation_version, created_at, updated_at) + VALUES (?, 'AWAITING_REVIEW', 'review_and_submit', 'waiting_human', 'required', 3, ?, ?); + `, id, u, ts, id, ts, ts) + if err != nil { + t.Fatal(err) + } +} + // TestDogfoodRun_EndToEnd exercises the whole cohort lifecycle through this // package's own handlers plus the storage layer's confirmation path, the same // way a real five-application dogfood run would: start, confirm five @@ -138,17 +142,7 @@ func TestDogfoodRun_EndToEnd(t *testing.T) { now := time.Now().UTC() for i := 1; i <= 5; i++ { - if _, err := db.Exec(`INSERT INTO job_funnel (url, id, company_name, job_title, status, discovered_at) - VALUES (?, ?, ?, 'Engineer', 'AWAITING_REVIEW', ?)`, - "https://boards.greenhouse.io/example/jobs/dogfood-"+string(rune('0'+i)), i, "Company", now); err != nil { - t.Fatal(err) - } - if _, err := db.Exec(`INSERT INTO assisted_applications - (job_id, original_status, next_action_code, assisted_state, revalidation_state, revalidation_version, created_at, updated_at) - VALUES (?, 'AWAITING_REVIEW', 'review_and_submit', 'waiting_human', 'required', 3, ?, ?)`, - i, now, now); err != nil { - t.Fatal(err) - } + seedTestDogfoodJob(t, i, now) jobID := string(rune('0' + i)) ordinal, err := storage.ConfirmAssistedSubmission(db, jobID) if err != nil { diff --git a/cmd/dashboard/knowledge_api_test.go b/cmd/dashboard/knowledge_api_test.go index 69e881b..e2b1e13 100644 --- a/cmd/dashboard/knowledge_api_test.go +++ b/cmd/dashboard/knowledge_api_test.go @@ -408,7 +408,7 @@ func TestServeKnowledgeProfile_KeepsBackupsBoundedAndPrivate(t *testing.T) { } // The newest are the ones kept, so a recent mistake is still recoverable. sort.Strings(backups) - if len(backups) > 0 && !strings.Contains(backups[len(backups)-1], "2026081") { + if len(backups) > 0 && !strings.Contains(backups[len(backups)-1], "2026") { t.Errorf("newest backup looks wrong: %s", backups[len(backups)-1]) } } diff --git a/cmd/dashboard/schema_upgrade_test.go b/cmd/dashboard/schema_upgrade_test.go index a8e08c6..3f8f613 100644 --- a/cmd/dashboard/schema_upgrade_test.go +++ b/cmd/dashboard/schema_upgrade_test.go @@ -93,16 +93,21 @@ func TestDashboardStartup_CreatesEveryTableAssistedApplyNeeds(t *testing.T) { } } -// The behavioural half: starting a session is the operation that actually -// failed. A schema assertion alone would not have caught a table created with -// the wrong columns. -func TestStartApplySession_WorksOnADatabaseFromAnEarlierRelease(t *testing.T) { +func setupUpgradedLegacyDB(t *testing.T) { + t.Helper() previous := db t.Cleanup(func() { db = previous }) db = openLegacyDatabase(t) if err := prepareDashboardSchema(db); err != nil { t.Fatalf("prepare dashboard schema: %v", err) } +} + +// The behavioural half: starting a session is the operation that actually +// failed. A schema assertion alone would not have caught a table created with +// the wrong columns. +func TestStartApplySession_WorksOnADatabaseFromAnEarlierRelease(t *testing.T) { + setupUpgradedLegacyDB(t) if _, err := db.Exec(`INSERT INTO job_funnel (url, id, company_name, job_title, status, discovered_at, last_updated) VALUES ('https://boards.greenhouse.io/example/jobs/1', 1, 'Example', 'Engineer', 'AWAITING_REVIEW', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)`); err != nil { t.Fatal(err) @@ -140,12 +145,7 @@ func controlRequest(t *testing.T, origin, host string) *httptest.ResponseRecorde } func TestApplySessionControl_AcceptsTheDashboardsOwnPortWhateverItIs(t *testing.T) { - previous := db - t.Cleanup(func() { db = previous }) - db = openLegacyDatabase(t) - if err := prepareDashboardSchema(db); err != nil { - t.Fatal(err) - } + setupUpgradedLegacyDB(t) // A dashboard started with -addr 127.0.0.1:8099 serves pages whose Origin // is that address. Before #539 this was rejected outright, which broke @@ -164,12 +164,7 @@ func TestApplySessionControl_AcceptsTheDashboardsOwnPortWhateverItIs(t *testing. // Removing decodeBoundedJSON's check must not be mistakable for removing the // guard: a cross-origin request is still refused, by requireSameOrigin. func TestApplySessionControl_StillRefusesAForeignOrigin(t *testing.T) { - previous := db - t.Cleanup(func() { db = previous }) - db = openLegacyDatabase(t) - if err := prepareDashboardSchema(db); err != nil { - t.Fatal(err) - } + setupUpgradedLegacyDB(t) for _, origin := range []string{ "http://evil.example.com", "http://127.0.0.1:9999", // right host, wrong port diff --git a/docs/index.html b/docs/index.html index 163ebe0..22823b8 100644 --- a/docs/index.html +++ b/docs/index.html @@ -3,22 +3,42 @@
- + +A local-first Go system for discovery, tailored documents, guarded browser work, and clear human handoffs. Built to make the work observable—not magical.
+Designed and engineered by William Elias, Career Agent Core is a local-first Go system for discovery, tailored documents, guarded browser work, and clear human handoffs. Built to make the work observable—not magical.
Core architectural decisions behind local-first autonomous application engineering.
+Web scraping and agentic workflows typically rely on heavy Python runtimes with brittle dependencies. Building in Go provides single-binary deployment, zero-runtime overhead, deterministic goroutine concurrency with bounded worker pools, and memory safety without garbage collection stalls during long-running browser automation runs.
+Untrusted third-party job postings frequently contain hidden zero-width text, prompt override instructions, or adversarial HTML markup designed to trick generative models into unauthorized actions. Career Agent Core routes all incoming job descriptions and DOM text through an isolated sanitizer and AST boilerplate filter before model reasoning occurs.
+Fully unconstrained application bots degrade candidate reputation by sending misaligned or low-quality documents. Career Agent Core prepares tailored resumes and pre-fills multi-step forms up to the final confirmation gate, pausing execution and surfacing an exact diff for human review before any destructive submission event occurs.
+Browser-controlling agents that follow arbitrary external links risk being redirected to internal private networks (localhost, 127.0.0.1, or cloud metadata endpoints). Career Agent Core implements resolver-bound dialers that explicitly validate target IP addresses against private CIDR ranges prior to socket connection.
+© 2026 William Elias (howlcipher). Agentic Workflow & Automation Platform.
+© 2026 William Elias (howlcipher). Agentic Workflow & Automation Platform.