@bongos/core 1.19.804 → 1.19.806
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.bongos-core.json +267 -242
- package/.claude/skills/ask-for-help/SKILL.md +6 -6
- package/.claude/skills/backlog-review/SKILL.md +1 -1
- package/.claude/skills/blocker-review/SKILL.md +7 -7
- package/.claude/skills/blocker-solve/SKILL.md +5 -5
- package/.claude/skills/bug-triage/SKILL.md +7 -7
- package/.claude/skills/builder-claim/SKILL.md +3 -3
- package/.claude/skills/builder-cost/SKILL.md +2 -2
- package/.claude/skills/builder-end/SKILL.md +2 -2
- package/.claude/skills/builder-exit/SKILL.md +7 -7
- package/.claude/skills/builder-key/SKILL.md +2 -2
- package/.claude/skills/builder-reauth/SKILL.md +2 -2
- package/.claude/skills/builder-redteam/SKILL.md +7 -7
- package/.claude/skills/builder-release/SKILL.md +2 -2
- package/.claude/skills/builder-sequence/SKILL.md +1 -1
- package/.claude/skills/builder-setup/SKILL.md +3 -3
- package/.claude/skills/builder-ship/SKILL.md +1 -1
- package/.claude/skills/builder-stage/SKILL.md +1 -1
- package/.claude/skills/builder-start/SKILL.md +1 -1
- package/.claude/skills/fix-task/SKILL.md +4 -4
- package/.claude/skills/goal-create/SKILL.md +18 -18
- package/.claude/skills/goal-review/SKILL.md +7 -7
- package/.claude/skills/grade-audit/SKILL.md +5 -5
- package/.claude/skills/grade-recover/SKILL.md +4 -4
- package/.claude/skills/grader-health/SKILL.md +6 -6
- package/.claude/skills/idea-triage/SKILL.md +14 -14
- package/.claude/skills/merge-mode/SKILL.md +3 -3
- package/.claude/skills/planning-session/SKILL.md +20 -20
- package/.claude/skills/priority-session/SKILL.md +10 -10
- package/.claude/skills/recall/SKILL.md +1 -1
- package/.claude/skills/scan-before-install/SKILL.md +3 -3
- package/.claude/skills/status/SKILL.md +2 -2
- package/.claude/skills/strand-fix/SKILL.md +2 -2
- package/clients/bongos-client/README.md +1 -1
- package/clients/bongos-client/bongos-client.global.js +2 -0
- package/clients/bongos-client/index.cjs +2 -0
- package/clients/bongos-client/index.d.ts +2 -0
- package/clients/bongos-client/index.mjs +2 -0
- package/docs/api/openapi.json +45 -11
- package/docs/api-reference.md +11 -10
- package/docs/copy-inventory.md +47 -34
- package/docs/copy-registry.json +200 -72
- package/docs/module-api-changelog.md +4 -0
- package/modules/builder-settings/profile-nudge-prefs.js +1 -1
- package/modules/builder-settings/render-prefs.js +1 -1
- package/modules/dev-box/app/README.md +1 -1
- package/modules/dev-box/app/src/gds-client.js +11 -9
- package/modules/dev-box/app/src/vendor/bongos-client.cjs +2 -0
- package/modules/dev-box/app/test/unit.mjs +13 -13
- package/modules/dev-box/box-access.js +3 -3
- package/modules/dev-box/box-onboard.js +7 -7
- package/modules/discord/bug-attachments.js +1 -1
- package/modules/economy/cost-classify.js +6 -6
- package/modules/grading/grader-rubric.json +1 -1
- package/modules/grading/grader-score.js +1 -1
- package/modules/hall-ui/module.json +1 -1
- package/modules/hall-ui/public/drachmae.js +3 -3
- package/modules/hall-ui/public/goals-page.js +1 -1
- package/modules/hall-ui/public/goals-render.js +144 -22
- package/modules/hall-ui/public/goals.css +16 -1
- package/modules/hall-ui/public/idea.js +1 -1
- package/modules/hall-ui/public/md-reader.js +1 -1
- package/modules/hall-ui/public/people.html +1 -1
- package/modules/hall-ui/public/people.js +2 -2
- package/modules/hall-ui/public/primer.js +4 -4
- package/modules/hall-ui/public/roster.js +1 -1
- package/modules/hall-ui/public/shell.js +1 -1
- package/modules/hall-ui/public/task.js +1 -1
- package/modules/ideas/inbox.js +2 -2
- package/modules/lifecycle/db-analytics.js +1 -1
- package/modules/lifecycle/done-when.js +4 -4
- package/modules/lifecycle/version-close.js +1 -1
- package/modules/memory/learnings.js +2 -2
- package/modules/memory/memory.js +1 -1
- package/modules/onboarding/onboarding.js +1 -1
- package/modules/platform-identity/routes/my-projects.js +1 -1
- package/modules/platform-identity/routes/sso.js +2 -2
- package/modules/public-landing/public/index.html +2 -2
- package/modules/public-landing/public/projects-floor.states.json +1 -1
- package/modules/public-landing/public/projects.html +1 -1
- package/modules/public-landing/public/projects.states.json +1 -1
- package/modules/sessions/db.js +120 -0
- package/modules/sessions/module.json +2 -2
- package/modules/sessions/pollers/session-upload-health.js +111 -0
- package/modules/sessions/pulse.js +2 -2
- package/modules/sessions/routes/sessions.js +46 -0
- package/modules/sessions/upload-health.js +197 -0
- package/modules/status-ui/module.json +1 -1
- package/modules/status-ui/public/explore.js +1 -1
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/scripts/gds/agent-invoke.js +3 -3
- package/scripts/gds/api.js +4 -4
- package/scripts/gds/api.sh +1 -1
- package/scripts/gds/architect-audit.js +1 -1
- package/scripts/gds/artifact-audit.js +2 -2
- package/scripts/gds/audit-ships.js +2 -2
- package/scripts/gds/backfill-cost.js +1 -1
- package/scripts/gds/backfill-sessions.js +1 -1
- package/scripts/gds/backfill-subagent-rewards.js +1 -1
- package/scripts/gds/backfill-task-rewards.js +2 -2
- package/scripts/gds/box-auth-check.js +1 -1
- package/scripts/gds/box-sync.js +3 -3
- package/scripts/gds/box.js +10 -10
- package/scripts/gds/build-cli-package.js +3 -3
- package/scripts/gds/capture.js +2 -2
- package/scripts/gds/ci-grade.js +1 -1
- package/scripts/gds/claim-recall.js +2 -2
- package/scripts/gds/cli-lib.js +3 -3
- package/scripts/gds/context-pack.js +1 -1
- package/scripts/gds/copy-apply.js +2 -2
- package/scripts/gds/dev-lib.js +2 -2
- package/scripts/gds/fetch-art-key.js +2 -2
- package/scripts/gds/fetch-sound-prefs.js +3 -3
- package/scripts/gds/grade-smoke.js +1 -1
- package/scripts/gds/hooks/pre-push.js +1 -1
- package/scripts/gds/init.js +9 -9
- package/scripts/gds/key-card.js +1 -1
- package/scripts/gds/learning-capture.js +2 -2
- package/scripts/gds/linkify-refs.js +2 -2
- package/scripts/gds/local-preview-lib.js +1 -1
- package/scripts/gds/login.js +11 -10
- package/scripts/gds/main-audit.js +1 -1
- package/scripts/gds/newcomer-floor.config.json +1 -1
- package/scripts/gds/newcomer-floor.js +2 -2
- package/scripts/gds/newcomer-floor.templates.json +2 -2
- package/scripts/gds/onboarding-ship.js +1 -1
- package/scripts/gds/paste-token.js +3 -3
- package/scripts/gds/portability-smoke-memory.sh +5 -5
- package/scripts/gds/prove-strict-versioning.js +2 -2
- package/scripts/gds/provision-net.js +2 -2
- package/scripts/gds/provision-units.js +3 -3
- package/scripts/gds/pulse.js +2 -2
- package/scripts/gds/push-path-brief.js +2 -2
- package/scripts/gds/reauth.js +1 -1
- package/scripts/gds/recall.js +1 -1
- package/scripts/gds/redteam-patrol.js +3 -3
- package/scripts/gds/render-ideas.js +5 -5
- package/scripts/gds/repo-metrics.js +1 -1
- package/scripts/gds/sandbox-stage.js +3 -3
- package/scripts/gds/seed-adopt-tasks.js +3 -3
- package/scripts/gds/seed-board-room-tasks.js +1 -1
- package/scripts/gds/seed-bongos-app-tasks.js +2 -2
- package/scripts/gds/seed-bongos-coreB-tranche1-tasks.js +3 -3
- package/scripts/gds/seed-bongos-coreB-tranche2-tasks.js +4 -4
- package/scripts/gds/seed-bongos-tasks.js +5 -5
- package/scripts/gds/seed-bongos-v1-idea-routing-tasks.js +1 -1
- package/scripts/gds/seed-bongos-v1-seo-tasks.js +1 -1
- package/scripts/gds/seed-bv1-community-tasks.js +1 -1
- package/scripts/gds/seed-bv1-privacy-invites-tasks.js +1 -1
- package/scripts/gds/seed-bv1-profile-page-tasks.js +1 -1
- package/scripts/gds/seed-bv1-profiles-tasks.js +1 -1
- package/scripts/gds/seed-bv1-r01-delta-tasks.js +1 -1
- package/scripts/gds/seed-gds-v4-tasks.js +3 -3
- package/scripts/gds/seed-medusa-tasks.js +1 -1
- package/scripts/gds/seed-productization-tasks.js +1 -1
- package/scripts/gds/seed-project-admin-console-tasks.js +1 -1
- package/scripts/gds/seed-provisioning-tasks.js +2 -2
- package/scripts/gds/seed-strict-versioning-tasks.js +3 -3
- package/scripts/gds/seed-v2-world-tasks.js +2 -2
- package/scripts/gds/seed-verify-criteria.js +1 -1
- package/scripts/gds/session-digest.js +1 -1
- package/scripts/gds/session.js +2 -2
- package/scripts/gds/setup.js +7 -7
- package/scripts/gds/ship-flow.js +3 -3
- package/scripts/gds/ship-grade-steps.js +3 -3
- package/scripts/gds/ship-memory-sync.js +1 -1
- package/scripts/gds/ship-session-upload.js +3 -3
- package/scripts/gds/smoke-batch-claim.sh +10 -10
- package/scripts/gds/smoke-batch-release.sh +14 -14
- package/scripts/gds/smoke-claim-consistency.sh +19 -19
- package/scripts/gds/smoke-dependencies.sh +9 -9
- package/scripts/gds/smoke-write.sh +11 -11
- package/scripts/gds/start.js +1 -1
- package/scripts/gds/status.js +2 -2
- package/scripts/gds/strand-watch.js +1 -1
- package/scripts/gds/triage.js +4 -4
- package/scripts/gds/version-close.js +2 -2
- package/scripts/hall-preview/README.md +1 -1
- package/scripts/hall-preview/server.js +1 -1
- package/src/bongos/auth-admission.js +3 -3
- package/src/bongos/auth-idp.js +2 -2
- package/src/bongos/auth.js +3 -3
- package/src/bongos/db.js +2 -2
- package/src/bongos/llm-cache.js +2 -2
- package/src/bongos/metrics.js +1 -1
- package/src/bongos/middleware/audit.js +3 -3
- package/src/bongos/middleware/rate-limit.js +1 -1
- package/src/bongos/platform-visibility-gate.js +2 -2
- package/src/bongos/routes/_helpers.js +1 -1
- package/src/bongos/routes/audit-log.js +1 -1
- package/src/bongos/routes/auth.js +5 -5
- package/src/bongos/routes/backup.js +1 -1
- package/src/bongos/routes/builders.js +1 -1
- package/src/bongos/routes/instance.js +1 -1
- package/src/bongos/routes/live.js +1 -1
- package/src/bongos/routes/me.js +2 -2
- package/src/bongos/routes/modules.js +2 -2
- package/src/bongos/routes/public.js +1 -1
- package/src/bongos/routes/security.js +4 -4
- package/src/bongos/routes.js +1 -1
- package/src/bongos/serve-internal.js +6 -6
- package/src/branding.js +1 -1
- package/src/module-api.js +1 -1
- package/src/module-seams.js +2 -2
- package/src/platform-server.js +2 -2
- package/tests/api_alias_exceptions.mjs +67 -0
- package/tests/application_echo.mjs +12 -12
- package/tests/artifact_audit.mjs +1 -1
- package/tests/auth_page_gate.mjs +4 -4
- package/tests/auth_web_recovery.mjs +11 -11
- package/tests/bongos_login.mjs +7 -4
- package/tests/box_env.mjs +6 -6
- package/tests/bug_attachments.mjs +1 -1
- package/tests/cli_sessions.mjs +1 -1
- package/tests/dev_lib.mjs +1 -1
- package/tests/discord_bugs.mjs +2 -2
- package/tests/discord_inbound.mjs +2 -2
- package/tests/explore_visible_states.mjs +1 -1
- package/tests/goal_invite_consent.mjs +307 -0
- package/tests/government_page_gates.mjs +1 -1
- package/tests/hall_reference_world.mjs +1 -1
- package/tests/idea_ideate_full.mjs +1 -1
- package/tests/idp_federation.mjs +2 -2
- package/tests/llm-cache.mjs +1 -1
- package/tests/manage_manifest_shared_read.mjs +3 -3
- package/tests/people_directory_clip.mjs +1 -1
- package/tests/planning_session_skill.mjs +1 -1
- package/tests/platform_visibility_gate.mjs +15 -15
- package/tests/profile_route.mjs +25 -25
- package/tests/projects_hub.mjs +2 -2
- package/tests/provision.mjs +2 -2
- package/tests/provision_settings_apply.mjs +4 -4
- package/tests/sandbox_stage.mjs +8 -8
- package/tests/scouting_owner_access_and_reach.mjs +3 -3
- package/tests/session_upload_health.mjs +329 -0
- package/tests/setup_device_flow_fallback.mjs +1 -1
- package/tests/skill_ask_for_help.mjs +3 -3
- package/tests/skill_grade_audit.mjs +2 -2
- package/tests/skill_grader_health.mjs +3 -3
- package/tests/smoke_write_contract.mjs +1 -1
package/src/bongos/db.js
CHANGED
|
@@ -737,7 +737,7 @@ async function revokeSession(token) {
|
|
|
737
737
|
|
|
738
738
|
// revokeSessionById — V3.R38 / #259. Kill ONE session by primary key. Returns
|
|
739
739
|
// the number of rows revoked (0 if id didn't exist or was already revoked, 1
|
|
740
|
-
// otherwise). Used by POST /api/
|
|
740
|
+
// otherwise). Used by POST /api/bongos/auth/revoke (Archon-only).
|
|
741
741
|
|
|
742
742
|
async function revokeSessionById(sessionId) {
|
|
743
743
|
const { rowCount } = await pool.query(
|
|
@@ -751,7 +751,7 @@ async function revokeSessionById(sessionId) {
|
|
|
751
751
|
|
|
752
752
|
// revokeAllSessionsForBuilder — V3.R38 / #259. Kill EVERY non-revoked session
|
|
753
753
|
// for a single builder. Returns the count of sessions revoked. Used by:
|
|
754
|
-
// * POST /api/
|
|
754
|
+
// * POST /api/bongos/auth/revoke-all (Archon-only direct call)
|
|
755
755
|
// * setBuilderRank when newRank < oldRank (rank-change-near-instant per C7)
|
|
756
756
|
|
|
757
757
|
async function revokeAllSessionsForBuilder(builderId) {
|
package/src/bongos/llm-cache.js
CHANGED
|
@@ -151,7 +151,7 @@ async function lookup(cacheKey, { tokensSavedEst = 0 } = {}) {
|
|
|
151
151
|
// must never take down the thing it accelerates.
|
|
152
152
|
if (_apiCall) {
|
|
153
153
|
try {
|
|
154
|
-
const r = await _apiCall('POST', '/api/
|
|
154
|
+
const r = await _apiCall('POST', '/api/bongos/llm-cache/lookup',
|
|
155
155
|
{ cache_key: cacheKey, tokens_saved_est: est }, { allowUnauthenticated: true });
|
|
156
156
|
if (r && r.ok && r.data && r.data.hit) return r.data.result || null;
|
|
157
157
|
} catch (_) { /* network/auth error → miss */ }
|
|
@@ -185,7 +185,7 @@ async function store(spec, { resultStdout, resultCostUsd = 0 } = {}) {
|
|
|
185
185
|
// cost server-side; best-effort: any error → no-store (never throws).
|
|
186
186
|
if (_apiCall) {
|
|
187
187
|
try {
|
|
188
|
-
const r = await _apiCall('POST', '/api/
|
|
188
|
+
const r = await _apiCall('POST', '/api/bongos/llm-cache/store',
|
|
189
189
|
{ spec, result_stdout: resultStdout, result_cost_usd: Number(resultCostUsd) || 0 },
|
|
190
190
|
{ allowUnauthenticated: true });
|
|
191
191
|
return !!(r && r.ok && r.data && r.data.stored);
|
package/src/bongos/metrics.js
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
// - process/runtime: uptime, RSS, heap, CPU (counter), event-loop lag, build_info
|
|
15
15
|
// - HTTP (from httpMiddleware): gds_http_requests_total{method,route,status} +
|
|
16
16
|
// gds_http_request_duration_seconds histogram — route normalized to a
|
|
17
|
-
// low-cardinality template so /api/
|
|
17
|
+
// low-cardinality template so /api/bongos/tasks/1380 and /…/1381 share a series.
|
|
18
18
|
// Gives error-rate + 4xx/5xx per route. 401/403 also bump gds_auth_failures_total.
|
|
19
19
|
// - DB gauges (collected at scrape, read-only — never instruments the gate-floor
|
|
20
20
|
// ship pipeline): tasks-by-status, claims (all-time + active), builders-by-rank,
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
// src/bongos/middleware/audit.js — append-only audit log for authenticated writes
|
|
2
2
|
// (V3.R35 / #256).
|
|
3
3
|
//
|
|
4
|
-
// Wire-up: mounted INSIDE the /api/
|
|
4
|
+
// Wire-up: mounted INSIDE the /api/bongos sub-router by routes.js, AFTER the JSON
|
|
5
5
|
// body parser and AFTER each route's auth middleware has run (the middleware
|
|
6
6
|
// fires on res 'finish', so by then auth either populated req.builder or sent
|
|
7
7
|
// a 401 — both cases are handled below).
|
|
8
8
|
//
|
|
9
9
|
// What it captures:
|
|
10
|
-
// - Every authenticated POST/PATCH/PUT/DELETE that the /api/
|
|
10
|
+
// - Every authenticated POST/PATCH/PUT/DELETE that the /api/bongos router
|
|
11
11
|
// served. Reads (GET) are explicitly skipped — they're high-volume and
|
|
12
12
|
// low-signal for forensics.
|
|
13
13
|
// - The redacted request body, the response status the client actually saw,
|
|
@@ -161,7 +161,7 @@ function clientIp(req) {
|
|
|
161
161
|
// (e.g. 404 from the router), fall back to req.path.
|
|
162
162
|
function routePattern(req) {
|
|
163
163
|
if (req.route && req.route.path) {
|
|
164
|
-
// baseUrl carries '/api/
|
|
164
|
+
// baseUrl carries '/api/bongos' plus any sub-router prefix; combining them
|
|
165
165
|
// yields the full pattern. trim trailing slash for tidiness.
|
|
166
166
|
const base = (req.baseUrl || '').replace(/\/+$/, '');
|
|
167
167
|
const tail = req.route.path === '/' ? '' : req.route.path;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/bongos/middleware/rate-limit.js — V3.R34 (#255).
|
|
2
2
|
//
|
|
3
3
|
// Five sliding-window in-memory limiters. The first two are the GLOBAL pair and
|
|
4
|
-
// protect write methods on /api/
|
|
4
|
+
// protect write methods on /api/bongos/* only — read methods (GET, HEAD, OPTIONS)
|
|
5
5
|
// bypass them entirely; #3, #4 and #5 are mounted per-surface to close exactly that
|
|
6
6
|
// gap where an unauthenticated READ is itself the abuse.
|
|
7
7
|
//
|
|
@@ -127,7 +127,7 @@ function isGated() { return mode() === GATED; }
|
|
|
127
127
|
|
|
128
128
|
// Express routes case-insensitively and tolerates one trailing slash, so the
|
|
129
129
|
// exempt test must see the path the way the router will — otherwise a probe
|
|
130
|
-
// spelled `/HEALTHZ` or `/api/
|
|
130
|
+
// spelled `/HEALTHZ` or `/api/bongos/instance/` is refused while the router would
|
|
131
131
|
// have served it. Mismatches still fail CLOSED; this only keeps the list honest.
|
|
132
132
|
function normalizePath(p) {
|
|
133
133
|
let s = String(p || '').toLowerCase();
|
|
@@ -160,7 +160,7 @@ function productName() {
|
|
|
160
160
|
// subdomain, a dev port, or plain http would otherwise be dropped at the default
|
|
161
161
|
// page. Only a GET/HEAD path is safe to come back to; anything else returns to '/'.
|
|
162
162
|
function signInHref(req) {
|
|
163
|
-
const base = '/api/
|
|
163
|
+
const base = '/api/bongos/auth/web/start';
|
|
164
164
|
const back = (req.method === 'GET' || req.method === 'HEAD') ? relativeReturn(req.originalUrl) : null;
|
|
165
165
|
return back ? `${base}?return=${encodeURIComponent(back)}` : base;
|
|
166
166
|
}
|
|
@@ -409,7 +409,7 @@ function hardenRouterStack(router, seen = new Set()) {
|
|
|
409
409
|
// Read-only, no-auth, no-secret routes, so a static '*' is safe; the caller
|
|
410
410
|
// mounts it scoped to a `/public…` prefix (passed as `scope` for documentation
|
|
411
411
|
// + signature parity) so it can't leak onto the authenticated routes on the same
|
|
412
|
-
// /api/
|
|
412
|
+
// /api/bongos base. Behavior is BYTE-IDENTICAL to the two copy-pasted blocks it
|
|
413
413
|
// replaces (routes/analytics.js + routes/public.js): sets
|
|
414
414
|
// Access-Control-Allow-Origin:*, and answers an OPTIONS preflight with
|
|
415
415
|
// Allow-Methods 'GET, OPTIONS' + Allow-Headers 'Content-Type' and a 204.
|
|
@@ -14,7 +14,7 @@ const VALID_METHODS = new Set(['POST', 'PATCH', 'PUT', 'DELETE']);
|
|
|
14
14
|
module.exports = function buildAuditLogRouter() {
|
|
15
15
|
const router = express.Router();
|
|
16
16
|
|
|
17
|
-
// GET /api/
|
|
17
|
+
// GET /api/bongos/audit-log?limit=&offset=&builder_id=&method=
|
|
18
18
|
//
|
|
19
19
|
// Paginated, newest-first. Clamps:
|
|
20
20
|
// limit → 1..500, default 100
|
|
@@ -92,7 +92,7 @@ function renderAuthErrorPage(heading, detail, opts = {}) {
|
|
|
92
92
|
catch { return AUTH_ERROR_FALLBACK; }
|
|
93
93
|
})();
|
|
94
94
|
const subtitle = opts.subtitle || copy.subtitle;
|
|
95
|
-
const cta = opts.cta || { href: opts.startHref || '/api/
|
|
95
|
+
const cta = opts.cta || { href: opts.startHref || '/api/bongos/auth/web/start', label: copy.ctaLabel };
|
|
96
96
|
const note = opts.note || "If this keeps happening, the GitHub OAuth app's authorized callback URL may be misconfigured. See docs/recipes/ops-gotchas.md (GitHub OAuth section).";
|
|
97
97
|
// The instance name in the tab title comes from the branding pack, never a
|
|
98
98
|
// hardcoded host brand — a non-OTB instance sees its own name (ADR 0062 §3).
|
|
@@ -165,7 +165,7 @@ function renderAccessPendingPage(login, startHref) {
|
|
|
165
165
|
</header>
|
|
166
166
|
<main>
|
|
167
167
|
<section class="scroll">
|
|
168
|
-
<div class="landing" id="pending" data-login="${safeLogin}" data-start="${escapeHtml(startHref || '/api/
|
|
168
|
+
<div class="landing" id="pending" data-login="${safeLogin}" data-start="${escapeHtml(startHref || '/api/bongos/auth/web/start')}">
|
|
169
169
|
<p>We're checking your access now. You'll be signed in automatically as soon as it clears — no need to refresh.</p>
|
|
170
170
|
<p class="landing__note" id="pending-note">Checking…</p>
|
|
171
171
|
</div>
|
|
@@ -178,7 +178,7 @@ function renderAccessPendingPage(login, startHref) {
|
|
|
178
178
|
var login = el ? el.getAttribute('data-login') : '';
|
|
179
179
|
/* server-built from the still-valid handshake cookies (task 1003234): the
|
|
180
180
|
fresh sign-in keeps the wizard return + repo scope a founder started with */
|
|
181
|
-
var start = (el && el.getAttribute('data-start')) || '/api/
|
|
181
|
+
var start = (el && el.getAttribute('data-start')) || '/api/bongos/auth/web/start';
|
|
182
182
|
var EVERY_MS = 3000;
|
|
183
183
|
var GIVE_UP_MS = 5 * 60 * 1000;
|
|
184
184
|
var started = Date.now();
|
|
@@ -190,7 +190,7 @@ function renderAccessPendingPage(login, startHref) {
|
|
|
190
190
|
note.textContent = 'Still waiting on approval. You can leave this page open, or try signing in again later.';
|
|
191
191
|
return;
|
|
192
192
|
}
|
|
193
|
-
fetch('/api/
|
|
193
|
+
fetch('/api/bongos/auth/web/admission-status?login=' + encodeURIComponent(login), { credentials: 'omit' })
|
|
194
194
|
.then(function (r) { return r.ok ? r.json() : null; })
|
|
195
195
|
.then(function (j) {
|
|
196
196
|
if (j && j.admitted) { land(); return; }
|
|
@@ -350,7 +350,7 @@ function recoveryStartHref(req) {
|
|
|
350
350
|
if (returnTo) params.set('return', returnTo);
|
|
351
351
|
if (parseCookie(req, REPOS_COOKIE) === '1') params.set('repos', '1');
|
|
352
352
|
const q = params.toString();
|
|
353
|
-
return '/api/
|
|
353
|
+
return '/api/bongos/auth/web/start' + (q ? '?' + q : '');
|
|
354
354
|
}
|
|
355
355
|
|
|
356
356
|
// The canonical sign-in origin, read from the instance branding pack (oauthOrigin,
|
|
@@ -153,7 +153,7 @@ module.exports = function buildBackupRouter() {
|
|
|
153
153
|
|
|
154
154
|
res.status(202).json({
|
|
155
155
|
ok: true,
|
|
156
|
-
message: 'Backup started — poll GET /api/
|
|
156
|
+
message: 'Backup started — poll GET /api/bongos/backup/status to see the new dump land (usually < 30 s).',
|
|
157
157
|
started_at: startedAt,
|
|
158
158
|
});
|
|
159
159
|
}));
|
|
@@ -456,7 +456,7 @@ module.exports = function buildBuildersRouter() {
|
|
|
456
456
|
// Public read (no auth). Spec says the hall renders other builders'
|
|
457
457
|
// checklists read-only — a builder's onboarding progress is roster-visible
|
|
458
458
|
// signal, same posture as rank or drachmae shown on the leaderboard. The
|
|
459
|
-
// builder's own row is also surfaced inside /api/
|
|
459
|
+
// builder's own row is also surfaced inside /api/bongos/me; this endpoint is
|
|
460
460
|
// what the hall hits for the CURRENT viewer AND for any other builder
|
|
461
461
|
// whose card is rendered.
|
|
462
462
|
//
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// src/bongos/routes/instance.js — GET /api/
|
|
1
|
+
// src/bongos/routes/instance.js — GET /api/bongos/instance (V4.R82, task 1249, ADR 0062 / Cloud Bongos C8).
|
|
2
2
|
//
|
|
3
3
|
// The instance manifest: one public, pre-auth, read-only descriptor that a CLI
|
|
4
4
|
// (`bongos login <url>`) fetches to configure ITSELF — the conda
|
|
@@ -105,7 +105,7 @@ function streamLive(req, res, deps = {}) {
|
|
|
105
105
|
function buildLiveRouter() {
|
|
106
106
|
const router = express.Router();
|
|
107
107
|
|
|
108
|
-
// GET /api/
|
|
108
|
+
// GET /api/bongos/live — SSE stream of Bongos state-change nudges for the hall.
|
|
109
109
|
// rank: any-builder — requireBuilder gates anonymous/abuse traffic (defense
|
|
110
110
|
// in depth; the payload leaks nothing). Mirrors the room's #983 signed-in
|
|
111
111
|
// gate. EventSource carries the gds_session cookie on this same-origin GET, so
|
package/src/bongos/routes/me.js
CHANGED
|
@@ -157,7 +157,7 @@ module.exports = function buildMeRouter() {
|
|
|
157
157
|
// V3.R24 (#244): the `builder` payload now carries `karma` (migration 040
|
|
158
158
|
// added the column + karma_log table). The field is surfaced by
|
|
159
159
|
// db.getBuilderById() — no shape change here, just documenting that the
|
|
160
|
-
// /api/
|
|
160
|
+
// /api/bongos/me response is the canonical place clients read karma from.
|
|
161
161
|
//
|
|
162
162
|
// rank: any-builder — own identity + own contributions; preserved per CRITICAL §4.
|
|
163
163
|
router.get('/me', auth.requireBuilder, async (req, res) => {
|
|
@@ -621,7 +621,7 @@ module.exports = function buildMeRouter() {
|
|
|
621
621
|
// The five per-builder PREFERENCE routes — /me/skill-prefs, /me/sound-prefs,
|
|
622
622
|
// /me/event-sound-prefs, /me/wandering, /me/render (GET + PATCH each) — moved to
|
|
623
623
|
// modules/builder-settings/routes/settings.js (BV1.R80 / ADR 0093 §1). They keep
|
|
624
|
-
// their exact /me/* paths (the loader mounts that router on this same /api/
|
|
624
|
+
// their exact /me/* paths (the loader mounts that router on this same /api/bongos
|
|
625
625
|
// router, before the public catch-all), so the API is byte-identical. The GET
|
|
626
626
|
// /me aggregator above stays here as a thin facade resolving the
|
|
627
627
|
// `builder-settings` port for its wandering/render/needs slices (02-module-map §2).
|
|
@@ -148,7 +148,7 @@ module.exports = function buildModulesRouter() {
|
|
|
148
148
|
res.json({ ok: true, key, enabled, note: 'Live on this box now. Persisting past the next deploy needs config/modules.json committed.' });
|
|
149
149
|
}));
|
|
150
150
|
|
|
151
|
-
// POST /api/
|
|
151
|
+
// POST /api/bongos/modules/:key/submit — ADR 0107 §1 upstreaming submission.
|
|
152
152
|
//
|
|
153
153
|
// task 1770. Body: { signed_by?: "Name <email>" }. Re-runs the §4
|
|
154
154
|
// AGPL/publish pre-check + requires a DCO-style sign-off against THIS box's
|
|
@@ -213,7 +213,7 @@ module.exports = function buildModulesRouter() {
|
|
|
213
213
|
res.status(201).json({ ok: true, submission });
|
|
214
214
|
}));
|
|
215
215
|
|
|
216
|
-
// GET /api/
|
|
216
|
+
// GET /api/bongos/modules/submissions?status=&module_key= — the upstreaming
|
|
217
217
|
// review queue (task 1771 reads this). Metadata only — no file contents (a
|
|
218
218
|
// future GET .../:id can add a with-files fetch if the review UI needs it).
|
|
219
219
|
//
|
|
@@ -115,7 +115,7 @@ module.exports = function buildPublicRouter() {
|
|
|
115
115
|
// CORS for the public surface (ADR 0029 / #566): the off-box status page reads
|
|
116
116
|
// these cross-origin. Read-only, no-auth, no-secret routes, so a static '*' is
|
|
117
117
|
// safe; scoped to '/public' so it can't leak onto the authenticated routes on
|
|
118
|
-
// the same /api/
|
|
118
|
+
// the same /api/bongos base. No Vary:Origin — the ACAO never varies by origin.
|
|
119
119
|
// Shared middleware: corsPublicGet (_helpers.js) — byte-identical to analytics.js.
|
|
120
120
|
router.use('/public', corsPublicGet('/public'));
|
|
121
121
|
|
|
@@ -74,7 +74,7 @@ async function readFullAdr() {
|
|
|
74
74
|
module.exports = function buildSecurityRouter() {
|
|
75
75
|
const router = express.Router();
|
|
76
76
|
|
|
77
|
-
// GET /api/
|
|
77
|
+
// GET /api/bongos/security/adr
|
|
78
78
|
//
|
|
79
79
|
// Metic+ only. Returns the full security ADR as { adr_md, source,
|
|
80
80
|
// fetched_at } when the file is provisioned; otherwise 404 with a
|
|
@@ -125,7 +125,7 @@ module.exports = function buildSecurityRouter() {
|
|
|
125
125
|
// now `permission_forbidden`, not `rank_forbidden`.
|
|
126
126
|
// -----------------------------------------------------------------------
|
|
127
127
|
|
|
128
|
-
// GET /api/
|
|
128
|
+
// GET /api/bongos/security/docs — list doc METADATA (no content).
|
|
129
129
|
//
|
|
130
130
|
// rank: archon — index of exploit-detail engagement reports. Gate:
|
|
131
131
|
// requirePermission('security.report.adjudicate') — BV1.R104.
|
|
@@ -144,7 +144,7 @@ module.exports = function buildSecurityRouter() {
|
|
|
144
144
|
}
|
|
145
145
|
);
|
|
146
146
|
|
|
147
|
-
// GET /api/
|
|
147
|
+
// GET /api/bongos/security/docs/:slug — one doc WITH content, or 404.
|
|
148
148
|
//
|
|
149
149
|
// rank: archon — reads the full exploit-detail report body. Gate:
|
|
150
150
|
// requirePermission('security.report.adjudicate') — BV1.R104.
|
|
@@ -177,7 +177,7 @@ module.exports = function buildSecurityRouter() {
|
|
|
177
177
|
}
|
|
178
178
|
);
|
|
179
179
|
|
|
180
|
-
// POST /api/
|
|
180
|
+
// POST /api/bongos/security/docs — upsert a doc by slug. The director uploads
|
|
181
181
|
// each dated engagement report here after deploy.
|
|
182
182
|
//
|
|
183
183
|
// Body: { slug, title, content_md }. content_md uses a large explicit cap
|
package/src/bongos/routes.js
CHANGED
|
@@ -108,7 +108,7 @@ function buildGdsRouter() {
|
|
|
108
108
|
});
|
|
109
109
|
|
|
110
110
|
// Audit middleware (V3.R35 #256) — attaches a res 'finish' hook so every
|
|
111
|
-
// authenticated POST/PATCH/PUT/DELETE under /api/
|
|
111
|
+
// authenticated POST/PATCH/PUT/DELETE under /api/bongos is recorded in
|
|
112
112
|
// audit_log AFTER the response is sent. It cannot fail the request: throws
|
|
113
113
|
// are caught, DB errors are swallowed, and it never mutates req/res in a
|
|
114
114
|
// way downstream handlers can see. Mounted BEFORE the feature routers so
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
//
|
|
3
3
|
// Mounts every non-game surface the platform serves onto an Express app:
|
|
4
4
|
// * /healthz + /version — liveness + deployed-build info
|
|
5
|
-
// * /api/
|
|
5
|
+
// * /api/bongos/* — the GDS API (buildGdsRouter)
|
|
6
6
|
// * /downloads/devbox/* — Dev Box installer redirect surface (#904)
|
|
7
7
|
// * generic module web-surface — each enabled module's contributes.webSurfaces
|
|
8
8
|
// hosts served on its Host prefix by ONE generic static
|
|
@@ -179,7 +179,7 @@ function jsonForScript(value) {
|
|
|
179
179
|
// the pack wins. Applied to the boot-time stamped HTML maps (the pack is a
|
|
180
180
|
// boot-time singleton, computed once). Off-box surfaces that can't be
|
|
181
181
|
// server-injected (the GitHub-Pages status page) read the same projection from
|
|
182
|
-
// GET /api/
|
|
182
|
+
// GET /api/bongos/public/branding. Pure + exported for the unit test.
|
|
183
183
|
function injectBrandingGlobal(html, brand = clientBranding(), mods = clientModules()) {
|
|
184
184
|
// window.__MODULES__ — the enabled feature-module set (R54 task 1193, ADR 0062
|
|
185
185
|
// §4), injected the same way as __BRANDING__ so hall/status scripts can hide
|
|
@@ -456,7 +456,7 @@ function injectModuleHallWidgets(html, scripts = hallWidgetScripts({ isEnabled:
|
|
|
456
456
|
// builders.<apex> gets the builder surface (served by the hall-ui MODULE's web
|
|
457
457
|
// surface, BV1.R85 — its DEDICATED block below); the apex host gets the game
|
|
458
458
|
// (server.js) or — on a game-less instance — a plain 404 (platform-server.js). All
|
|
459
|
-
// share the same process + the same /api/
|
|
459
|
+
// share the same process + the same /api/bongos/* surface (mounted host-agnostically
|
|
460
460
|
// below). The prefix checks are apex-agnostic (any domain), so no brand string lives
|
|
461
461
|
// here. isStatusHost + isBuildersHost stay the literal "status."/"builders."
|
|
462
462
|
// predicates the entrypoints (server.js/platform-server.js) use to keep their apex
|
|
@@ -830,7 +830,7 @@ function mountInternalSurfaces(app) {
|
|
|
830
830
|
// clean path so the address bar never shows ".../builders". PAGE paths only —
|
|
831
831
|
// the slug is [a-z0-9-]+ with no dot, so asset URLs the pages emit
|
|
832
832
|
// (/builders/style.css, /builders/*.js, /builders/diagrams/*.png) and the API
|
|
833
|
-
// (/api/
|
|
833
|
+
// (/api/bongos/builders/*) never match and pass through to the shim below.
|
|
834
834
|
const BUILDERS_CANONICAL_RE = /^\/builders(?:\/([a-z0-9-]+))?\/?$/i;
|
|
835
835
|
app.use((req, res, next) => {
|
|
836
836
|
if (!isBuildersHost(req)) return next();
|
|
@@ -1056,8 +1056,8 @@ function mountInternalSurfaces(app) {
|
|
|
1056
1056
|
// read from BUILDERS_DIR. The module key is NOT named — the path is the
|
|
1057
1057
|
// hall-ui module's public dir, resolved once here.
|
|
1058
1058
|
//
|
|
1059
|
-
// Auth is handled client-side: the page calls /api/
|
|
1060
|
-
// the browser to /api/
|
|
1059
|
+
// Auth is handled client-side: the page calls /api/bongos/me; on 401 it redirects
|
|
1060
|
+
// the browser to /api/bongos/auth/web/start, which (per src/bongos/routes/auth.js)
|
|
1061
1061
|
// loops back to /builders with a gds_session cookie set.
|
|
1062
1062
|
const BUILDERS_DIR = path.join(ROOT, 'modules', 'hall-ui', 'public');
|
|
1063
1063
|
const buildersStatic = express.static(BUILDERS_DIR, {
|
package/src/branding.js
CHANGED
|
@@ -206,7 +206,7 @@ function userAgent() {
|
|
|
206
206
|
}
|
|
207
207
|
|
|
208
208
|
// The CLIENT-SAFE projection of the resolved pack — the subset the browser is
|
|
209
|
-
// allowed to see, served by GET /api/
|
|
209
|
+
// allowed to see, served by GET /api/bongos/public/branding and consumed by the
|
|
210
210
|
// hall + status front-ends. Deliberately a small allow-list, NOT the whole pack:
|
|
211
211
|
// origins, repo binding, db name, and env prefix are server-only and must never
|
|
212
212
|
// reach the client. R56 (task 1195) seeded it with the configurable currency
|
package/src/module-api.js
CHANGED
|
@@ -71,7 +71,7 @@ const { responsibilityFor, ROLE_RESPONSIBILITIES } = require('./role-responsibil
|
|
|
71
71
|
// there. scripts/gds/bump-version.js still rewrites the literal below; it appends
|
|
72
72
|
// the entry to that file. Look for a version's history there, not here.
|
|
73
73
|
// ---------------------------------------------------------------------------
|
|
74
|
-
const CORE_VERSION = '1.19.
|
|
74
|
+
const CORE_VERSION = '1.19.806'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
|
|
75
75
|
|
|
76
76
|
// A namespaced logger so a module's log lines are attributable + consistent.
|
|
77
77
|
// Usage: const log = api.logger('dev-box'); log.info('mounted');
|
package/src/module-seams.js
CHANGED
|
@@ -188,7 +188,7 @@ function listEvents() {
|
|
|
188
188
|
//
|
|
189
189
|
// Canonical extension points (the names core consumes):
|
|
190
190
|
// • 'profile.fields' — server-side: each contributor is `async (ctx) => ({…slice})`;
|
|
191
|
-
// the slices merge into the GET /api/
|
|
191
|
+
// the slices merge into the GET /api/bongos/me payload.
|
|
192
192
|
// (The client settings-panel seam is its browser twin,
|
|
193
193
|
// window.OTB.contributeSettingsPanel in dom-utils.js.)
|
|
194
194
|
|
|
@@ -240,7 +240,7 @@ async function collectContributions(point, ctx) {
|
|
|
240
240
|
// a module's contribution can't clobber a core field). Mutates + returns `base`,
|
|
241
241
|
// and reports any collided keys so the caller can surface them — that signals a
|
|
242
242
|
// move task took over a core key without first removing the core copy. Used by
|
|
243
|
-
// GET /api/
|
|
243
|
+
// GET /api/bongos/me to fold 'profile.fields' slices into the profile payload.
|
|
244
244
|
function mergeContributions(base, slices) {
|
|
245
245
|
const collisions = [];
|
|
246
246
|
for (const slice of slices || []) {
|
package/src/platform-server.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
// WHAT IT SERVES — the entire internal surface, via the shared mount that
|
|
8
8
|
// server.js also uses (so the two entrypoints never drift, ADR 0052):
|
|
9
9
|
// * /healthz + /version
|
|
10
|
-
// * /api/
|
|
10
|
+
// * /api/bongos/* — the full GDS API (buildGdsRouter)
|
|
11
11
|
// * the status dashboard host — modules/status-ui/public/ (the status-ui module's
|
|
12
12
|
// web surface, BV1.R84 — served by the loader seam)
|
|
13
13
|
// * the builders' hall host — modules/hall-ui/public/ (the hall-ui module's
|
|
@@ -269,7 +269,7 @@ function buildPlatformApp() {
|
|
|
269
269
|
});
|
|
270
270
|
}
|
|
271
271
|
|
|
272
|
-
// Non-game tail. Anything that did not resolve to /api/
|
|
272
|
+
// Non-game tail. Anything that did not resolve to /api/bongos, the status host,
|
|
273
273
|
// or the builders' hall lands here. There is NO game to fall through to, so:
|
|
274
274
|
// * an API-shaped path gets a self-describing JSON 404 (never HTML), the
|
|
275
275
|
// same contract server.js gives so a mis-prefixed CLI call is legible;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// tests/api_alias_exceptions.mjs — the callers task 1003707 deliberately LEFT on
|
|
2
|
+
// the permanent /api/gds alias, and the reason each one stays.
|
|
3
|
+
//
|
|
4
|
+
// WHY THIS FILE EXISTS. C3e moved every in-repo caller onto the canonical
|
|
5
|
+
// /api/bongos. A handful were held back on purpose, and "on purpose" is the kind
|
|
6
|
+
// of fact that survives exactly one sweep: the next agent greps for the old
|
|
7
|
+
// spelling, sees four stragglers, tidies them, and discovers what they were for
|
|
8
|
+
// when sign-in breaks. Each case below names its reason, so a future move has to
|
|
9
|
+
// argue with the reason rather than with a leftover.
|
|
10
|
+
//
|
|
11
|
+
// The mount itself is asserted by tests/rename_history_restraint.mjs (structure)
|
|
12
|
+
// and tests/api_path_404.mjs (dispatch — the alias is a live mount, so it gets no
|
|
13
|
+
// corrective 404 hint). Only the ONE line that makes the alias permanent is
|
|
14
|
+
// re-asserted here, because these exceptions are worthless without it.
|
|
15
|
+
import assert from 'node:assert/strict';
|
|
16
|
+
import { test } from 'node:test';
|
|
17
|
+
import fs from 'node:fs';
|
|
18
|
+
import path from 'node:path';
|
|
19
|
+
import { createRequire } from 'node:module';
|
|
20
|
+
import { fileURLToPath } from 'node:url';
|
|
21
|
+
|
|
22
|
+
const require = createRequire(import.meta.url);
|
|
23
|
+
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
24
|
+
const read = (rel) => fs.readFileSync(path.join(ROOT, rel), 'utf8');
|
|
25
|
+
const ALIAS = '/api/gds';
|
|
26
|
+
|
|
27
|
+
test('the alias is still mounted — everything below depends on it', () => {
|
|
28
|
+
const { API_PREFIX, LEGACY_API_PREFIXES, ALL_API_PREFIXES } = require(path.join(ROOT, 'src', 'bongos', 'api-prefix.js'));
|
|
29
|
+
assert.equal(API_PREFIX, '/api/bongos', 'the canonical prefix is what in-repo callers now ask for');
|
|
30
|
+
assert.ok(LEGACY_API_PREFIXES.includes(ALIAS), 'shipped Dev Box binaries and live dev boxes call the alias');
|
|
31
|
+
assert.ok(ALL_API_PREFIXES.includes(ALIAS), 'and the router still mounts it');
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test('the OAuth callbacks stay on the alias — they are registered outside this repo', () => {
|
|
35
|
+
const auth = read('src/bongos/routes/auth.js');
|
|
36
|
+
// Changing either of these needs a matching edit in the GitHub / Discord app
|
|
37
|
+
// settings; a repo-only change silently breaks sign-in. Pin the lines that BUILD
|
|
38
|
+
// the redirect_uri, not a mention of the path — auth.js also names it in an error
|
|
39
|
+
// message, and matching that would keep this green with both builders rewritten.
|
|
40
|
+
const webBuilders = auth.split(`\${WEB_REDIRECT_ORIGIN}${ALIAS}/auth/web/callback`).length - 1;
|
|
41
|
+
assert.equal(webBuilders, 2, 'both GitHub redirect_uri builders stay on the alias (auth.js WEB_REDIRECT_ORIGIN)');
|
|
42
|
+
assert.ok(auth.includes(`\${DISCORD_REDIRECT_ORIGIN}${ALIAS}/auth/discord/callback`),
|
|
43
|
+
'Discord OAuth app callback (DISCORD_REDIRECT_URI)');
|
|
44
|
+
// The instance provisioner registers the same pinned path for every new instance.
|
|
45
|
+
assert.ok(read('modules/provisioning/provisioning.js').includes(`${ALIAS}/auth/web/callback`),
|
|
46
|
+
'a provisioned instance registers the pinned callback, not the canonical one');
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test('the sign-in START href moved, and that is safe because the cookie is path-scoped to /', () => {
|
|
50
|
+
const auth = read('src/bongos/routes/auth.js');
|
|
51
|
+
assert.ok(auth.includes('/api/bongos/auth/web/start'), 'the start link asks for the canonical path');
|
|
52
|
+
assert.ok(/path: '\/'/.test(auth), 'the session cookie is set at path / — it reaches BOTH prefixes');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test('the uptime poller stays on the alias so production keeps exercising it', () => {
|
|
56
|
+
// If nothing in production ever calls the alias, its eventual breakage is
|
|
57
|
+
// discovered by a user rather than by us.
|
|
58
|
+
assert.ok(read('src/bongos/uptime-poller.js').includes(`${ALIAS}/healthz`),
|
|
59
|
+
'the poller is the one live caller that proves the alias answers');
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test('a pasted API base is stripped whichever spelling it carries', () => {
|
|
63
|
+
const { normalizeInstanceBase } = require(path.join(ROOT, 'scripts', 'gds', 'login.js'));
|
|
64
|
+
for (const suffix of ['/api/bongos', '/api/bongos/v1', '/api/gds', '/api/gds/']) {
|
|
65
|
+
assert.equal(normalizeInstanceBase(`https://example.com${suffix}`), 'https://example.com', suffix);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
@@ -274,7 +274,7 @@ const { attachFail } = require('../src/bongos/middleware/error-envelope.js');
|
|
|
274
274
|
let relay = { status: 201, body: { ok: true } };
|
|
275
275
|
const realFetch = globalThis.fetch;
|
|
276
276
|
globalThis.fetch = async (url) => {
|
|
277
|
-
if (String(url).endsWith('/api/
|
|
277
|
+
if (String(url).endsWith('/api/bongos/access-requests')) {
|
|
278
278
|
if (relay === null) throw new Error('connection refused');
|
|
279
279
|
return { status: relay.status, json: async () => relay.body };
|
|
280
280
|
}
|
|
@@ -285,7 +285,7 @@ after(() => { globalThis.fetch = realFetch; });
|
|
|
285
285
|
const app = express();
|
|
286
286
|
app.use(express.json());
|
|
287
287
|
app.use(attachFail);
|
|
288
|
-
app.use('/api/
|
|
288
|
+
app.use('/api/bongos', myProjectsRoutes());
|
|
289
289
|
|
|
290
290
|
let server, port;
|
|
291
291
|
before(async () => {
|
|
@@ -314,7 +314,7 @@ function call(method, pathname, body) {
|
|
|
314
314
|
req.end(payload);
|
|
315
315
|
});
|
|
316
316
|
}
|
|
317
|
-
const join = (note) => call('POST', '/api/
|
|
317
|
+
const join = (note) => call('POST', '/api/bongos/my-projects/join', { origin: 'https://target.example', note });
|
|
318
318
|
|
|
319
319
|
test('the interpreter refuses a predicate it cannot read — parameterised or not', () => {
|
|
320
320
|
assert.throws(() => predicateFor('github_id = $1::bigint AND something = $2', [1, 2]), /unread predicate on \$2/);
|
|
@@ -391,7 +391,7 @@ test('a failed echo write never turns a filed application into a reported failur
|
|
|
391
391
|
test('GET /my-projects reports what was applied to and when — and no status', async () => {
|
|
392
392
|
seed();
|
|
393
393
|
relay = { status: 201, body: { ok: true } };
|
|
394
|
-
const r = await call('GET', '/api/
|
|
394
|
+
const r = await call('GET', '/api/bongos/my-projects');
|
|
395
395
|
assert.equal(r.status, 200);
|
|
396
396
|
const applied = r.json.applied;
|
|
397
397
|
assert.deepEqual(applied.map((a) => a.client_id), ['proj-open', 'proj-invited'],
|
|
@@ -405,7 +405,7 @@ test('GET /my-projects reports what was applied to and when — and no status',
|
|
|
405
405
|
|
|
406
406
|
test('a project the applicant now BUILDS on drops out of applied — membership is the approval signal', async () => {
|
|
407
407
|
seed();
|
|
408
|
-
const r = await call('GET', '/api/
|
|
408
|
+
const r = await call('GET', '/api/bongos/my-projects');
|
|
409
409
|
assert.deepEqual(r.json.building.map((b) => b.client_id), ['proj-joined']);
|
|
410
410
|
assert.ok(!r.json.applied.some((a) => a.client_id === 'proj-joined'),
|
|
411
411
|
'an approval becomes visible by the card flipping to member, never by the echo claiming it');
|
|
@@ -421,7 +421,7 @@ test('a project the applicant now BUILDS on drops out of applied — membership
|
|
|
421
421
|
|
|
422
422
|
test('an echo older than the window is invisible, not deleted', async () => {
|
|
423
423
|
seed();
|
|
424
|
-
const r = await call('GET', '/api/
|
|
424
|
+
const r = await call('GET', '/api/bongos/my-projects');
|
|
425
425
|
assert.ok(!r.json.applied.some((a) => a.client_id === 'proj-stale'),
|
|
426
426
|
'a declined application must not read as "applied" forever');
|
|
427
427
|
assert.ok(echoes.some((e) => e.client_id === 'proj-stale'), 'and the row is still there — the window is read-time');
|
|
@@ -429,7 +429,7 @@ test('an echo older than the window is invisible, not deleted', async () => {
|
|
|
429
429
|
|
|
430
430
|
test('the echo read is own-scope: another account’s row is never reachable', async () => {
|
|
431
431
|
seed();
|
|
432
|
-
const r = await call('GET', '/api/
|
|
432
|
+
const r = await call('GET', '/api/bongos/my-projects');
|
|
433
433
|
assert.ok(!r.json.applied.some((a) => a.client_id === 'proj-someone-elses'));
|
|
434
434
|
const echoRead = statements.find((s) => /FROM platform_identity_application_echoes/.test(s.sql));
|
|
435
435
|
assert.match(echoRead.sql, /WHERE e\.github_id = \$1::bigint/, 'keyed on the session, never on anything from the request');
|
|
@@ -444,12 +444,12 @@ test('the echo read is own-scope: another account’s row is never reachable', a
|
|
|
444
444
|
test('leaving a project forgets the application that got you in', async () => {
|
|
445
445
|
seed();
|
|
446
446
|
assert.ok(echo('proj-joined'), 'precondition: the echo from the original application is still on file');
|
|
447
|
-
const left = await call('POST', '/api/
|
|
447
|
+
const left = await call('POST', '/api/bongos/my-projects/proj-joined/leave');
|
|
448
448
|
assert.equal(left.status, 200);
|
|
449
449
|
assert.equal(left.json.left, true);
|
|
450
450
|
assert.equal(echo('proj-joined'), undefined, 'the echo goes with the membership');
|
|
451
451
|
|
|
452
|
-
const after = await call('GET', '/api/
|
|
452
|
+
const after = await call('GET', '/api/bongos/my-projects');
|
|
453
453
|
assert.ok(!after.json.building.some((b) => b.client_id === 'proj-joined'));
|
|
454
454
|
assert.ok(!after.json.applied.some((a) => a.client_id === 'proj-joined'),
|
|
455
455
|
'and it does NOT come back as "applied" now that the membership no longer hides it');
|
|
@@ -457,7 +457,7 @@ test('leaving a project forgets the application that got you in', async () => {
|
|
|
457
457
|
|
|
458
458
|
test('leaving forgets only the leaver’s own echo, for only that project', async () => {
|
|
459
459
|
seed();
|
|
460
|
-
await call('POST', '/api/
|
|
460
|
+
await call('POST', '/api/bongos/my-projects/proj-joined/leave');
|
|
461
461
|
assert.ok(echo('proj-open'), 'a different project of mine is untouched');
|
|
462
462
|
assert.ok(echoes.some((e) => e.client_id === 'proj-someone-elses'), 'and so is another account’s row');
|
|
463
463
|
});
|
|
@@ -465,7 +465,7 @@ test('leaving forgets only the leaver’s own echo, for only that project', asyn
|
|
|
465
465
|
test('a failed echo cleanup does not fail a leave that already happened', async () => {
|
|
466
466
|
seed();
|
|
467
467
|
echoFails = true;
|
|
468
|
-
const left = await call('POST', '/api/
|
|
468
|
+
const left = await call('POST', '/api/bongos/my-projects/proj-joined/leave');
|
|
469
469
|
assert.equal(left.status, 200, 'the membership is already gone — the echo is a convenience, not the act');
|
|
470
470
|
assert.equal(left.json.left, true);
|
|
471
471
|
});
|
|
@@ -473,7 +473,7 @@ test('a failed echo cleanup does not fail a leave that already happened', async
|
|
|
473
473
|
test('a failed echo read costs the applied list and nothing else', async () => {
|
|
474
474
|
seed();
|
|
475
475
|
echoFails = true;
|
|
476
|
-
const r = await call('GET', '/api/
|
|
476
|
+
const r = await call('GET', '/api/bongos/my-projects');
|
|
477
477
|
assert.equal(r.status, 200);
|
|
478
478
|
assert.deepEqual(r.json.applied, []);
|
|
479
479
|
assert.deepEqual(r.json.building.map((b) => b.client_id), ['proj-joined'], 'the memberships listing still lands');
|
package/tests/artifact_audit.mjs
CHANGED
|
@@ -171,7 +171,7 @@ await t('a finding is filed to the blocker surface, not only printed', async ()
|
|
|
171
171
|
const call = async (method, path, body) => { sent.push({ method, path, body }); return { ok: true, status: 201, data: { blocker: { id: 42 } } }; };
|
|
172
172
|
const r = await fileBlocker([{ id: '1003188', status: 'shipped', shipped_at: '2026-08-23', title: 'Go-live', touches: ['package.json'] }], { call });
|
|
173
173
|
assert.equal(r.filed, true);
|
|
174
|
-
assert.equal(sent[0].path, '/api/
|
|
174
|
+
assert.equal(sent[0].path, '/api/bongos/blockers');
|
|
175
175
|
assert.equal(sent[0].body.source, 'artifact-audit');
|
|
176
176
|
assert.match(sent[0].body.body_md, /task 1003188/);
|
|
177
177
|
});
|