@bongos/core 1.25.11 → 1.25.13
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 +120 -30
- package/clients/bongos-client/README.md +1 -1
- package/clients/bongos-client/bongos-client.global.js +16 -0
- package/clients/bongos-client/index.cjs +16 -0
- package/clients/bongos-client/index.d.ts +22 -0
- package/clients/bongos-client/index.mjs +16 -0
- package/docs/adr/0406-every-project-gets-a-sandbox-that-follows-main-and-live-moves-only-when-a-person-promotes.md +108 -0
- package/docs/adr/README.md +1 -0
- package/docs/api/openapi.json +376 -3
- package/docs/api-reference.md +13 -1
- package/docs/file-map.md +1 -0
- package/docs/module-api-changelog.md +4 -0
- package/modules/front-door-guide/CLAUDE.md +15 -0
- package/modules/front-door-guide/claude.js +55 -0
- package/modules/front-door-guide/context.js +54 -0
- package/modules/front-door-guide/db.js +137 -0
- package/modules/front-door-guide/guide.js +148 -0
- package/modules/front-door-guide/limits.js +87 -0
- package/modules/front-door-guide/migrations/front_door_guide_001_conversations.sql +48 -0
- package/modules/front-door-guide/migrations/front_door_guide_002_plan_and_account.sql +37 -0
- package/modules/front-door-guide/module.json +31 -0
- package/modules/front-door-guide/plan.js +93 -0
- package/modules/front-door-guide/pollers/retention-sweep.js +67 -0
- package/modules/front-door-guide/routes/front-door-guide-plan.js +144 -0
- package/modules/front-door-guide/routes/front-door-guide.js +196 -0
- package/modules/front-door-guide/settings.js +72 -0
- package/modules/provisioning/module.json +2 -1
- package/modules/provisioning/seams.js +10 -0
- package/modules/provisioning/starter-bundles.js +3 -1
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/release-notes.json +16 -0
- package/scripts/bongos/publish-manifest.js +1 -0
- package/scripts/bongos/run-unit-tests.js +4 -0
- package/src/bongos/module-scope-map.js +6 -0
- package/src/module-api.js +1 -1
- package/tests/front_door_guide.mjs +410 -0
- package/tests/front_door_guide_db.mjs +110 -0
- package/tests/front_door_guide_plan.mjs +344 -0
- package/tests/module_loader.mjs +1 -1
package/docs/api/openapi.json
CHANGED
|
@@ -141,6 +141,10 @@
|
|
|
141
141
|
"name": "founding",
|
|
142
142
|
"description": "Endpoints under `/api/bongos/founding`."
|
|
143
143
|
},
|
|
144
|
+
{
|
|
145
|
+
"name": "front-door-guide",
|
|
146
|
+
"description": "Endpoints under `/api/bongos/front-door-guide`."
|
|
147
|
+
},
|
|
144
148
|
{
|
|
145
149
|
"name": "github",
|
|
146
150
|
"description": "Endpoints under `/api/bongos/github`."
|
|
@@ -7889,6 +7893,287 @@
|
|
|
7889
7893
|
]
|
|
7890
7894
|
}
|
|
7891
7895
|
},
|
|
7896
|
+
"/front-door-guide/conversations": {
|
|
7897
|
+
"post": {
|
|
7898
|
+
"operationId": "post_front_door_guide_conversations",
|
|
7899
|
+
"tags": [
|
|
7900
|
+
"front-door-guide"
|
|
7901
|
+
],
|
|
7902
|
+
"summary": "POST /front-door-guide/conversations",
|
|
7903
|
+
"description": "start a chat. Answers the greeting and the conversation's token.\n\n**Rank:** `public` — No authentication — any caller.",
|
|
7904
|
+
"x-rank": "public",
|
|
7905
|
+
"x-source": "modules/front-door-guide/routes/front-door-guide.js",
|
|
7906
|
+
"requestBody": {
|
|
7907
|
+
"required": false,
|
|
7908
|
+
"content": {
|
|
7909
|
+
"application/json": {
|
|
7910
|
+
"schema": {
|
|
7911
|
+
"$ref": "#/components/schemas/PostFrontDoorGuideConversationsRequest"
|
|
7912
|
+
}
|
|
7913
|
+
}
|
|
7914
|
+
},
|
|
7915
|
+
"x-validated": true
|
|
7916
|
+
},
|
|
7917
|
+
"responses": {
|
|
7918
|
+
"200": {
|
|
7919
|
+
"description": "Success."
|
|
7920
|
+
},
|
|
7921
|
+
"400": {
|
|
7922
|
+
"$ref": "#/components/responses/ValidationFailed"
|
|
7923
|
+
}
|
|
7924
|
+
},
|
|
7925
|
+
"security": []
|
|
7926
|
+
}
|
|
7927
|
+
},
|
|
7928
|
+
"/front-door-guide/conversations/{id}": {
|
|
7929
|
+
"get": {
|
|
7930
|
+
"operationId": "get_front_door_guide_conversations_id",
|
|
7931
|
+
"tags": [
|
|
7932
|
+
"front-door-guide"
|
|
7933
|
+
],
|
|
7934
|
+
"summary": "GET /front-door-guide/conversations/:id",
|
|
7935
|
+
"description": "the transcript, for the plan and the sign-up hand-off.\n\n**Rank:** `public` — No authentication — any caller.",
|
|
7936
|
+
"x-rank": "public",
|
|
7937
|
+
"x-source": "modules/front-door-guide/routes/front-door-guide.js",
|
|
7938
|
+
"parameters": [
|
|
7939
|
+
{
|
|
7940
|
+
"name": "id",
|
|
7941
|
+
"in": "path",
|
|
7942
|
+
"required": true,
|
|
7943
|
+
"schema": {
|
|
7944
|
+
"type": "string"
|
|
7945
|
+
},
|
|
7946
|
+
"description": "Path parameter `id`."
|
|
7947
|
+
}
|
|
7948
|
+
],
|
|
7949
|
+
"responses": {
|
|
7950
|
+
"200": {
|
|
7951
|
+
"description": "Success."
|
|
7952
|
+
},
|
|
7953
|
+
"400": {
|
|
7954
|
+
"$ref": "#/components/responses/BadRequest"
|
|
7955
|
+
},
|
|
7956
|
+
"404": {
|
|
7957
|
+
"$ref": "#/components/responses/NotFound"
|
|
7958
|
+
}
|
|
7959
|
+
},
|
|
7960
|
+
"security": []
|
|
7961
|
+
}
|
|
7962
|
+
},
|
|
7963
|
+
"/front-door-guide/conversations/{id}/attach": {
|
|
7964
|
+
"post": {
|
|
7965
|
+
"operationId": "post_front_door_guide_conversations_id_attach",
|
|
7966
|
+
"tags": [
|
|
7967
|
+
"front-door-guide"
|
|
7968
|
+
],
|
|
7969
|
+
"summary": "POST /front-door-guide/conversations/:id/attach",
|
|
7970
|
+
"description": "the visitor has just signed in; the chat moves onto their account.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
|
|
7971
|
+
"x-rank": "any-builder",
|
|
7972
|
+
"x-source": "modules/front-door-guide/routes/front-door-guide-plan.js",
|
|
7973
|
+
"parameters": [
|
|
7974
|
+
{
|
|
7975
|
+
"name": "id",
|
|
7976
|
+
"in": "path",
|
|
7977
|
+
"required": true,
|
|
7978
|
+
"schema": {
|
|
7979
|
+
"type": "string"
|
|
7980
|
+
},
|
|
7981
|
+
"description": "Path parameter `id`."
|
|
7982
|
+
}
|
|
7983
|
+
],
|
|
7984
|
+
"requestBody": {
|
|
7985
|
+
"required": true,
|
|
7986
|
+
"content": {
|
|
7987
|
+
"application/json": {
|
|
7988
|
+
"schema": {
|
|
7989
|
+
"$ref": "#/components/schemas/PostFrontDoorGuideConversationsIdAttachRequest"
|
|
7990
|
+
}
|
|
7991
|
+
}
|
|
7992
|
+
},
|
|
7993
|
+
"x-validated": true
|
|
7994
|
+
},
|
|
7995
|
+
"responses": {
|
|
7996
|
+
"200": {
|
|
7997
|
+
"description": "Success.",
|
|
7998
|
+
"content": {
|
|
7999
|
+
"application/json": {
|
|
8000
|
+
"schema": {
|
|
8001
|
+
"$ref": "#/components/schemas/PostFrontDoorGuideConversationsIdAttachResponse"
|
|
8002
|
+
}
|
|
8003
|
+
}
|
|
8004
|
+
}
|
|
8005
|
+
},
|
|
8006
|
+
"400": {
|
|
8007
|
+
"$ref": "#/components/responses/ValidationFailed"
|
|
8008
|
+
},
|
|
8009
|
+
"401": {
|
|
8010
|
+
"$ref": "#/components/responses/Unauthorized"
|
|
8011
|
+
},
|
|
8012
|
+
"403": {
|
|
8013
|
+
"$ref": "#/components/responses/Forbidden"
|
|
8014
|
+
},
|
|
8015
|
+
"404": {
|
|
8016
|
+
"$ref": "#/components/responses/NotFound"
|
|
8017
|
+
}
|
|
8018
|
+
},
|
|
8019
|
+
"security": [
|
|
8020
|
+
{
|
|
8021
|
+
"builderSession": []
|
|
8022
|
+
}
|
|
8023
|
+
]
|
|
8024
|
+
}
|
|
8025
|
+
},
|
|
8026
|
+
"/front-door-guide/conversations/{id}/messages": {
|
|
8027
|
+
"post": {
|
|
8028
|
+
"operationId": "post_front_door_guide_conversations_id_messages",
|
|
8029
|
+
"tags": [
|
|
8030
|
+
"front-door-guide"
|
|
8031
|
+
],
|
|
8032
|
+
"summary": "POST /front-door-guide/conversations/:id/messages",
|
|
8033
|
+
"description": "one visitor message, one guide reply.\n\n**Rank:** `public` — No authentication — any caller.",
|
|
8034
|
+
"x-rank": "public",
|
|
8035
|
+
"x-source": "modules/front-door-guide/routes/front-door-guide.js",
|
|
8036
|
+
"parameters": [
|
|
8037
|
+
{
|
|
8038
|
+
"name": "id",
|
|
8039
|
+
"in": "path",
|
|
8040
|
+
"required": true,
|
|
8041
|
+
"schema": {
|
|
8042
|
+
"type": "string"
|
|
8043
|
+
},
|
|
8044
|
+
"description": "Path parameter `id`."
|
|
8045
|
+
}
|
|
8046
|
+
],
|
|
8047
|
+
"requestBody": {
|
|
8048
|
+
"required": true,
|
|
8049
|
+
"content": {
|
|
8050
|
+
"application/json": {
|
|
8051
|
+
"schema": {
|
|
8052
|
+
"$ref": "#/components/schemas/PostFrontDoorGuideConversationsIdMessagesRequest"
|
|
8053
|
+
}
|
|
8054
|
+
}
|
|
8055
|
+
},
|
|
8056
|
+
"x-validated": true
|
|
8057
|
+
},
|
|
8058
|
+
"responses": {
|
|
8059
|
+
"200": {
|
|
8060
|
+
"description": "Success."
|
|
8061
|
+
},
|
|
8062
|
+
"400": {
|
|
8063
|
+
"$ref": "#/components/responses/ValidationFailed"
|
|
8064
|
+
},
|
|
8065
|
+
"404": {
|
|
8066
|
+
"$ref": "#/components/responses/NotFound"
|
|
8067
|
+
}
|
|
8068
|
+
},
|
|
8069
|
+
"security": []
|
|
8070
|
+
}
|
|
8071
|
+
},
|
|
8072
|
+
"/front-door-guide/conversations/{id}/plan": {
|
|
8073
|
+
"post": {
|
|
8074
|
+
"operationId": "post_front_door_guide_conversations_id_plan",
|
|
8075
|
+
"tags": [
|
|
8076
|
+
"front-door-guide"
|
|
8077
|
+
],
|
|
8078
|
+
"summary": "POST /front-door-guide/conversations/:id/plan",
|
|
8079
|
+
"description": "the visitor has no account yet.\n\n**Rank:** `public` — No authentication — any caller.",
|
|
8080
|
+
"x-rank": "public",
|
|
8081
|
+
"x-source": "modules/front-door-guide/routes/front-door-guide-plan.js",
|
|
8082
|
+
"parameters": [
|
|
8083
|
+
{
|
|
8084
|
+
"name": "id",
|
|
8085
|
+
"in": "path",
|
|
8086
|
+
"required": true,
|
|
8087
|
+
"schema": {
|
|
8088
|
+
"type": "string"
|
|
8089
|
+
},
|
|
8090
|
+
"description": "Path parameter `id`."
|
|
8091
|
+
}
|
|
8092
|
+
],
|
|
8093
|
+
"requestBody": {
|
|
8094
|
+
"required": true,
|
|
8095
|
+
"content": {
|
|
8096
|
+
"application/json": {
|
|
8097
|
+
"schema": {
|
|
8098
|
+
"$ref": "#/components/schemas/PostFrontDoorGuideConversationsIdPlanRequest"
|
|
8099
|
+
}
|
|
8100
|
+
}
|
|
8101
|
+
},
|
|
8102
|
+
"x-validated": true
|
|
8103
|
+
},
|
|
8104
|
+
"responses": {
|
|
8105
|
+
"200": {
|
|
8106
|
+
"description": "Success."
|
|
8107
|
+
},
|
|
8108
|
+
"400": {
|
|
8109
|
+
"$ref": "#/components/responses/ValidationFailed"
|
|
8110
|
+
},
|
|
8111
|
+
"404": {
|
|
8112
|
+
"$ref": "#/components/responses/NotFound"
|
|
8113
|
+
}
|
|
8114
|
+
},
|
|
8115
|
+
"security": []
|
|
8116
|
+
}
|
|
8117
|
+
},
|
|
8118
|
+
"/front-door-guide/mine": {
|
|
8119
|
+
"get": {
|
|
8120
|
+
"operationId": "get_front_door_guide_mine",
|
|
8121
|
+
"tags": [
|
|
8122
|
+
"front-door-guide"
|
|
8123
|
+
],
|
|
8124
|
+
"summary": "GET /front-door-guide/mine",
|
|
8125
|
+
"description": "my newest chat and plan (the creation wizard's pre-fill reads it).\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
|
|
8126
|
+
"x-rank": "any-builder",
|
|
8127
|
+
"x-source": "modules/front-door-guide/routes/front-door-guide-plan.js",
|
|
8128
|
+
"responses": {
|
|
8129
|
+
"200": {
|
|
8130
|
+
"description": "Success.",
|
|
8131
|
+
"content": {
|
|
8132
|
+
"application/json": {
|
|
8133
|
+
"schema": {
|
|
8134
|
+
"$ref": "#/components/schemas/GetFrontDoorGuideMineResponse"
|
|
8135
|
+
}
|
|
8136
|
+
}
|
|
8137
|
+
}
|
|
8138
|
+
},
|
|
8139
|
+
"400": {
|
|
8140
|
+
"$ref": "#/components/responses/BadRequest"
|
|
8141
|
+
},
|
|
8142
|
+
"401": {
|
|
8143
|
+
"$ref": "#/components/responses/Unauthorized"
|
|
8144
|
+
},
|
|
8145
|
+
"403": {
|
|
8146
|
+
"$ref": "#/components/responses/Forbidden"
|
|
8147
|
+
}
|
|
8148
|
+
},
|
|
8149
|
+
"security": [
|
|
8150
|
+
{
|
|
8151
|
+
"builderSession": []
|
|
8152
|
+
}
|
|
8153
|
+
]
|
|
8154
|
+
}
|
|
8155
|
+
},
|
|
8156
|
+
"/front-door-guide/status": {
|
|
8157
|
+
"get": {
|
|
8158
|
+
"operationId": "get_front_door_guide_status",
|
|
8159
|
+
"tags": [
|
|
8160
|
+
"front-door-guide"
|
|
8161
|
+
],
|
|
8162
|
+
"summary": "GET /front-door-guide/status",
|
|
8163
|
+
"description": "the landing asks before it offers the chat.\n\n**Rank:** `public` — No authentication — any caller.",
|
|
8164
|
+
"x-rank": "public",
|
|
8165
|
+
"x-source": "modules/front-door-guide/routes/front-door-guide.js",
|
|
8166
|
+
"responses": {
|
|
8167
|
+
"200": {
|
|
8168
|
+
"description": "Success."
|
|
8169
|
+
},
|
|
8170
|
+
"400": {
|
|
8171
|
+
"$ref": "#/components/responses/BadRequest"
|
|
8172
|
+
}
|
|
8173
|
+
},
|
|
8174
|
+
"security": []
|
|
8175
|
+
}
|
|
8176
|
+
},
|
|
7892
8177
|
"/github/orgs": {
|
|
7893
8178
|
"get": {
|
|
7894
8179
|
"operationId": "get_github_orgs",
|
|
@@ -33576,6 +33861,19 @@
|
|
|
33576
33861
|
"count"
|
|
33577
33862
|
]
|
|
33578
33863
|
},
|
|
33864
|
+
"GetFrontDoorGuideMineResponse": {
|
|
33865
|
+
"type": "object",
|
|
33866
|
+
"properties": {
|
|
33867
|
+
"ok": {
|
|
33868
|
+
"type": "boolean"
|
|
33869
|
+
},
|
|
33870
|
+
"conversation": {}
|
|
33871
|
+
},
|
|
33872
|
+
"required": [
|
|
33873
|
+
"ok",
|
|
33874
|
+
"conversation"
|
|
33875
|
+
]
|
|
33876
|
+
},
|
|
33579
33877
|
"GetGithubOrgsOrgResponse": {
|
|
33580
33878
|
"type": "object",
|
|
33581
33879
|
"properties": {
|
|
@@ -38086,6 +38384,81 @@
|
|
|
38086
38384
|
},
|
|
38087
38385
|
"additionalProperties": false
|
|
38088
38386
|
},
|
|
38387
|
+
"PostFrontDoorGuideConversationsIdAttachRequest": {
|
|
38388
|
+
"type": "object",
|
|
38389
|
+
"properties": {
|
|
38390
|
+
"token": {
|
|
38391
|
+
"type": "string",
|
|
38392
|
+
"maxLength": 64
|
|
38393
|
+
}
|
|
38394
|
+
},
|
|
38395
|
+
"required": [
|
|
38396
|
+
"token"
|
|
38397
|
+
],
|
|
38398
|
+
"additionalProperties": false
|
|
38399
|
+
},
|
|
38400
|
+
"PostFrontDoorGuideConversationsIdAttachResponse": {
|
|
38401
|
+
"type": "object",
|
|
38402
|
+
"properties": {
|
|
38403
|
+
"ok": {
|
|
38404
|
+
"type": "boolean"
|
|
38405
|
+
},
|
|
38406
|
+
"conversation": {}
|
|
38407
|
+
},
|
|
38408
|
+
"required": [
|
|
38409
|
+
"ok",
|
|
38410
|
+
"conversation"
|
|
38411
|
+
]
|
|
38412
|
+
},
|
|
38413
|
+
"PostFrontDoorGuideConversationsIdMessagesRequest": {
|
|
38414
|
+
"type": "object",
|
|
38415
|
+
"properties": {
|
|
38416
|
+
"token": {
|
|
38417
|
+
"type": "string",
|
|
38418
|
+
"maxLength": 64
|
|
38419
|
+
},
|
|
38420
|
+
"text": {
|
|
38421
|
+
"type": "string",
|
|
38422
|
+
"maxLength": 100000
|
|
38423
|
+
},
|
|
38424
|
+
"website": {
|
|
38425
|
+
"type": "string",
|
|
38426
|
+
"maxLength": 500
|
|
38427
|
+
}
|
|
38428
|
+
},
|
|
38429
|
+
"required": [
|
|
38430
|
+
"token",
|
|
38431
|
+
"text"
|
|
38432
|
+
],
|
|
38433
|
+
"additionalProperties": false
|
|
38434
|
+
},
|
|
38435
|
+
"PostFrontDoorGuideConversationsIdPlanRequest": {
|
|
38436
|
+
"type": "object",
|
|
38437
|
+
"properties": {
|
|
38438
|
+
"token": {
|
|
38439
|
+
"type": "string",
|
|
38440
|
+
"maxLength": 64
|
|
38441
|
+
},
|
|
38442
|
+
"website": {
|
|
38443
|
+
"type": "string",
|
|
38444
|
+
"maxLength": 500
|
|
38445
|
+
}
|
|
38446
|
+
},
|
|
38447
|
+
"required": [
|
|
38448
|
+
"token"
|
|
38449
|
+
],
|
|
38450
|
+
"additionalProperties": false
|
|
38451
|
+
},
|
|
38452
|
+
"PostFrontDoorGuideConversationsRequest": {
|
|
38453
|
+
"type": "object",
|
|
38454
|
+
"properties": {
|
|
38455
|
+
"website": {
|
|
38456
|
+
"type": "string",
|
|
38457
|
+
"maxLength": 500
|
|
38458
|
+
}
|
|
38459
|
+
},
|
|
38460
|
+
"additionalProperties": false
|
|
38461
|
+
},
|
|
38089
38462
|
"PostGithubRepoInviteRequest": {
|
|
38090
38463
|
"type": "object",
|
|
38091
38464
|
"properties": {
|
|
@@ -43973,9 +44346,9 @@
|
|
|
43973
44346
|
"description": "A required dependency/feature is not configured or is temporarily down."
|
|
43974
44347
|
}
|
|
43975
44348
|
},
|
|
43976
|
-
"x-endpoint-count":
|
|
43977
|
-
"x-schema-count":
|
|
44349
|
+
"x-endpoint-count": 709,
|
|
44350
|
+
"x-schema-count": 745,
|
|
43978
44351
|
"x-undocumented-bodies": 12,
|
|
43979
|
-
"x-response-schemas":
|
|
44352
|
+
"x-response-schemas": 468,
|
|
43980
44353
|
"x-generated-by": "scripts/bongos/gen-api-docs.js"
|
|
43981
44354
|
}
|
package/docs/api-reference.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# Bongos API reference
|
|
4
4
|
|
|
5
|
-
> **Generated from the live route files** — the route file is authoritative.
|
|
5
|
+
> **Generated from the live route files** — the route file is authoritative. 709 endpoints across 120 route files.
|
|
6
6
|
> Machine-readable spec: [`docs/api/openapi.json`](api/openapi.json) (OpenAPI 3.1). Rendered docs site: **`/docs`** (e.g. `cloudbongos.com/docs`).
|
|
7
7
|
|
|
8
8
|
Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/0016-trust-boundary-server-enforced-permissions.md)): `public` < `any-builder` < `metic+archon` < `archon`.
|
|
@@ -328,6 +328,18 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/0016-trust
|
|
|
328
328
|
| POST | `/api/bongos/founding/stages/:stage/close` | `any-builder` | — | task 1005121: one call. |
|
|
329
329
|
| POST | `/api/bongos/founding/start` | `any-builder` | — | |
|
|
330
330
|
|
|
331
|
+
## `front-door-guide` (7)
|
|
332
|
+
|
|
333
|
+
| Method | Path | Rank | Body | Description |
|
|
334
|
+
|---|---|---|---|---|
|
|
335
|
+
| POST | `/api/bongos/front-door-guide/conversations` | `public` | `website` | start a chat. |
|
|
336
|
+
| GET | `/api/bongos/front-door-guide/conversations/:id` | `public` | — | the transcript, for the plan and the sign-up hand-off. |
|
|
337
|
+
| POST | `/api/bongos/front-door-guide/conversations/:id/attach` | `any-builder` | `token` | the visitor has just signed in; the chat moves onto their account. |
|
|
338
|
+
| POST | `/api/bongos/front-door-guide/conversations/:id/messages` | `public` | `token`, `text`, `website` | one visitor message, one guide reply. |
|
|
339
|
+
| POST | `/api/bongos/front-door-guide/conversations/:id/plan` | `public` | `token`, `website` | the visitor has no account yet. |
|
|
340
|
+
| GET | `/api/bongos/front-door-guide/mine` | `any-builder` | — | my newest chat and plan (the creation wizard's pre-fill reads it). |
|
|
341
|
+
| GET | `/api/bongos/front-door-guide/status` | `public` | — | the landing asks before it offers the chat. |
|
|
342
|
+
|
|
331
343
|
## `github` (8)
|
|
332
344
|
|
|
333
345
|
| Method | Path | Rank | Body | Description |
|
package/docs/file-map.md
CHANGED
|
@@ -116,6 +116,7 @@
|
|
|
116
116
|
│ ├── copy-desk/ ← CORE-DOMAIN module (task 1003113 / R02 of goal 1000074, default-on): the COPY half of the design contract — ADR 0081 gave design TOKENS a repo-owned source of truth, text had none. Owns the FLAG (anyone in any role marks a string or a whole surface as needing an artist's attention, with a reason required in BOTH the route and a CHECK constraint) and the QUEUE an artist reads it from. READS R01's committed registry (docs/copy-registry.json, generated by scripts/bongos/copy-inventory.js) and never writes it. NO LIVE CMS is the hard non-goal: no column here could hold replacement text, and copy_no_cms.mjs pins that. Key is `copy-desk`, not `copy` — the branding contract already owns a `copy` block, so the bare word reds the "core carries no module code" fitness check. R03 (task 1003114, ADR 0233) added the PROPOSAL: an artist writes the replacement wording and it becomes a Bongos task carrying a fenced copy-proposal patch — no row, NO second migration (a proposals table is the forbidden column with extra steps), and scripts/bongos/copy-apply.js lands it as a real diff under a claim. BV2.TW05 (task 1004316, ADR 0341 D8) added Tweak Mode's three derived READS — GET /copy-desk/pages, /copy-desk/pages/:pageId, /copy-desk/tally: page status and count, changelog, drift, "N of M tweaked" per surface, and the artist's tally — over the page-tweak tasks (lifecycle port), docs/page-inventory.json and docs/page-readings.json (both now in the publish manifest), with no status table. BV2.TW06 (task 1004317, ADR 0341 D2, D5, D6) added its first two page WRITES: POST /copy-desk/pages/:pageId/claim (an artist-craft builder opens or takes the page's tweak round as a web-claimed task, through the lifecycle port's webClaimPageTweak, under an advisory lock on the page) and POST /copy-desk/pages/:pageId/asks (anyone files a page ask, a copy_desk_flags row with scope 'page', added by copy_desk_002_page_asks.sql). CLAUDE.md, module.json, registry.js, flags.js, proposals.js, pages.js (the page-tweak block format), page-status.js (the pure derivation), page-data.js (the page artifacts' read side), routes/copy-desk.js, migrations/copy_desk_001_flags.sql, migrations/copy_desk_002_page_asks.sql, tests/{copy_flags,copy_queue,copy_no_cms,copy_proposals,copy_page_status}.mjs + tests/fixtures/page-tweak.cjs. Its hall surface lives with hall-ui (public/copy-desk.{html,js,css}), per the one-key-per-web-surface precedent. skills/tweak/SKILL.md is the /tweak skill (contributes.skills; moved out of .claude/skills/ in task 1004471, hidden from the model listing, typed as /tweak).
|
|
117
117
|
│ ├── page-notes/ ← the artist's page feedback docs (task 1004496, default-on): the Artistry palette button's store. A doc about one hall page, with up to eight reference images (stored in the DB, images only), turned into ideas by an AI split on submit and kept as the page's reference (?note=N). Apart from copy-desk, which may hold no wording. module.json, CLAUDE.md, notes.js (pure), split.js, db.js, routes/, migrations/.
|
|
118
118
|
│ ├── ai-studio/ ← AI generation for artists (task 1004916, ADR 0392, default-off; hub first): a sketch or image set plus a prompt gets a Gemini reply and generated images on our key (processor-held balance, one named price multiplier, funds held first, released on failure) or the builder's own key (no charge). Keys entered only in Settings, never leave the server. module.json, CLAUDE.md, routes/.
|
|
119
|
+
│ ├── front-door-guide/ ← the start-a-project guide (task 1005272, goal 1000106, default-off; hub first): a signed-out visitor talks with an AI guide for a few capped messages before signing up, on the platform's own Anthropic key from the environment. Every cap on the server (messages and spend per visitor, daily and monthly site budget, message length, rate limits, bot check); a spent budget or no key answers the plain form. The chat ends in a structured plan naming only modules the creation picker offers (the provisioning.moduleCatalog port), saved, attached to the account at sign-up, and swept after a set number of days if nobody signs up (task 1005273). module.json, CLAUDE.md (the response shape), settings.js, guide.js, plan.js, context.js, claude.js, limits.js, db.js, routes/, pollers/retention-sweep.js, migrations/.
|
|
119
120
|
│ ├── market-watch/ ← Market Watch (task 1004935, goal 1000137, default-off): a weekly AI watch on a project's competitors, partners and topics. No routes yet; the manifest declares spend.requiresPayer. Kept out of the creation picker (HUB_ONLY_MODULES) until it does something. Data layer (task 1004936): migrations/ (market_watch_* tables), db.js (read queries), seed.js + seed/ (the 2026-10-28 research, hub only), pollers/hub-seed.js. module.json, CLAUDE.md.
|
|
120
121
|
│ ├── raise/ ← the /raise investor page (task 1004847, ADR 0384, default-off; hub only): password-gated for investors (signing in accepts the NDA, non-binding interest), edited in place by any active builder with every change logged. The copy in content/ is the owner's words — never reword it in code. module.json, CLAUDE.md, raise.js (pure), page.js, web.js (the GET-only raise.web port core mounts at /raise), db.js, routes/ (every write), migrations/, content/, views/, public/.
|
|
121
122
|
│ ├── npm-release/ ← the deploy page for a project that publishes an npm package from GitHub (task 1002622, default-OFF — on only in the Bongos hall, which publishes @bongos/core). "Where the work is": every task finished in the last 14 days, placed in the stage it has actually reached (not merged · merged, no version yet · published, not running here · running here, not released · released · in no version), plus the version history — each version's tasks. The version↔task join reads the release-notes.json the package itself carries (scripts/bongos/release-notes.js writes it at pack time), streamed out of the NEWEST version's npm tarball in-process (no child process, no sync call) when the running core's own copy stops short. module.json, work.js (the reading + the stage placement — the packument, tarball stream and tar reader it uses are the core's src/bongos/package-registry.js, reached through the doorway's readPackageRegistry since task 1004296), routes/work.js (GET /npm-release/work, gated core.pin.move like the page), public/work.{js,css} (the two sections /deploy lends it: #nr-work, #nr-versions). Task 1004301 added the same line on a task's own page: routes/task-where.js (GET /npm-release/task/:id, any signed-in builder — it shows nothing not already public) + public/task-widget.js, injected into task.html by the loader's uiSections seam (hallWidgetScripts file task-widget.js) to fill #task-contrib on otb:task-shown. Tests sit at the repo root — tests/npm_release_{work,page}.mjs — because a default-off module's own tests/ is skipped by the unit runner.
|
|
@@ -3462,5 +3462,9 @@ is load-bearing: the script throws rather than guess if it is missing, and
|
|
|
3462
3462
|
landed since 1.25.9 with no explicit bump. run 43417745698. (task 1002620)
|
|
3463
3463
|
1.25.11 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
3464
3464
|
landed since 1.25.10 with no explicit bump. run 43440873455. (task 1002620)
|
|
3465
|
+
1.25.12 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
3466
|
+
landed since 1.25.11 with no explicit bump. run 43489275620. (task 1002620)
|
|
3467
|
+
1.25.13 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
3468
|
+
landed since 1.25.12 with no explicit bump. run 43493844051. (task 1002620)
|
|
3465
3469
|
---------------------------------------------------------------------------
|
|
3466
3470
|
```
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# @bongos/core — installed platform dependency (not your project's CLAUDE.md)
|
|
2
|
+
|
|
3
|
+
This file is a placeholder shipped inside the **@bongos/core** package. The core's own
|
|
4
|
+
internal agent notes are intentionally omitted from the published artifact so they cannot
|
|
5
|
+
load into your instance's context.
|
|
6
|
+
|
|
7
|
+
**It does not govern this repository.** Your own root `CLAUDE.md`, your `.claude/`
|
|
8
|
+
directory, and the live Bongos database are the source of truth for how work happens here
|
|
9
|
+
and who may do what.
|
|
10
|
+
|
|
11
|
+
You are seeing this only because an agent opened a file under `node_modules/@bongos/core/`.
|
|
12
|
+
Nothing in here needs to be read to use the platform — run `bongos help` for commands.
|
|
13
|
+
|
|
14
|
+
_To work ON the platform core itself, use the standalone @bongos/core source repository,
|
|
15
|
+
not this vendored copy._
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// modules/front-door-guide/claude.js — the one Claude Messages API call behind the
|
|
2
|
+
// start-a-project guide (task 1005272), on the platform's own key.
|
|
3
|
+
//
|
|
4
|
+
// The SDK is required lazily, so an instance with the guide off never loads it, and the
|
|
5
|
+
// client is injectable so the tests run a mocked one and never spend real money.
|
|
6
|
+
// Thinking cannot be switched off on the default model; `effort` keeps a chat reply
|
|
7
|
+
// short and cheap, and `max_tokens` bounds the bill of one reply (thinking included).
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const CALL_TIMEOUT_MS = 30_000;
|
|
12
|
+
|
|
13
|
+
// createClient(apiKey, { sdk }) — the live client. The key goes only to the SDK.
|
|
14
|
+
function createClient(apiKey, { sdk = null } = {}) {
|
|
15
|
+
const mod = sdk || require('@anthropic-ai/sdk');
|
|
16
|
+
const Anthropic = mod.Anthropic || mod.default || mod;
|
|
17
|
+
return new Anthropic({ apiKey, timeout: CALL_TIMEOUT_MS, maxRetries: 1 });
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// buildRequest — the request body, kept separate so a test can read it. With `schema`
|
|
21
|
+
// it is the plan call: structured output (a JSON schema the reply must match) and the
|
|
22
|
+
// plan's own token ceiling.
|
|
23
|
+
function buildRequest({ settings, system, messages, schema = null }) {
|
|
24
|
+
const outputConfig = { effort: settings.effort };
|
|
25
|
+
if (schema) outputConfig.format = { type: 'json_schema', schema };
|
|
26
|
+
return {
|
|
27
|
+
model: settings.model,
|
|
28
|
+
max_tokens: schema ? settings.maxPlanTokens : settings.maxReplyTokens,
|
|
29
|
+
output_config: outputConfig,
|
|
30
|
+
system,
|
|
31
|
+
messages: messages.map((m) => ({ role: m.role, content: m.content })),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// askGuide({ client, settings, system, messages, schema? }) →
|
|
36
|
+
// { ok: true, stopReason, content, usage, model }
|
|
37
|
+
// { ok: false, error } a thrown SDK error (network, 4xx, 5xx); nothing was billed.
|
|
38
|
+
// Never throws.
|
|
39
|
+
async function askGuide({ client, settings, system, messages, schema = null }) {
|
|
40
|
+
let res;
|
|
41
|
+
try {
|
|
42
|
+
res = await client.messages.create(buildRequest({ settings, system, messages, schema }));
|
|
43
|
+
} catch (e) {
|
|
44
|
+
return { ok: false, error: `api_error${e && e.status ? ` ${e.status}` : ''}` };
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
ok: true,
|
|
48
|
+
stopReason: res && res.stop_reason,
|
|
49
|
+
content: (res && res.content) || [],
|
|
50
|
+
usage: (res && res.usage) || {},
|
|
51
|
+
model: (res && res.model) || settings.model,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
module.exports = { createClient, buildRequest, askGuide, CALL_TIMEOUT_MS };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// modules/front-door-guide/context.js — what both of the guide's routes files share (task
|
|
2
|
+
// 1005273): the visitor-hash salt, the product name, the module catalog, the site budget
|
|
3
|
+
// check, and ONE set of in-flight spend reservations. One set, because a chat reply and a
|
|
4
|
+
// plan from the same visitor, or from the whole site, must count against the same money.
|
|
5
|
+
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const api = require('../../src/module-api');
|
|
9
|
+
const db = require('./db');
|
|
10
|
+
const L = require('./limits');
|
|
11
|
+
|
|
12
|
+
const reservations = L.makeReservations();
|
|
13
|
+
|
|
14
|
+
function salt() {
|
|
15
|
+
let s;
|
|
16
|
+
try { s = api.resolveEnv('FRONT_DOOR_GUIDE_SALT'); } catch (_) { s = null; }
|
|
17
|
+
if (s) return s;
|
|
18
|
+
let name = 'bongos';
|
|
19
|
+
try { name = api.instanceDbName() || name; } catch (_) { /* the default salt still separates visitors */ }
|
|
20
|
+
return `front-door-guide:${name}`;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function productName() {
|
|
24
|
+
try { return api.branding().identity.productName || 'Cloud Bongos'; } catch (_) { return 'Cloud Bongos'; }
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// The modules a new project can opt into, from the provisioning module's port (the
|
|
28
|
+
// project-creation picker's own list). No provider (provisioning off) → an empty
|
|
29
|
+
// catalog, and the plan recommends nothing rather than guessing.
|
|
30
|
+
async function moduleCatalog() {
|
|
31
|
+
const provider = api.resolveOptional('provisioning.moduleCatalog');
|
|
32
|
+
if (typeof provider !== 'function') return { core: [], optional: [] };
|
|
33
|
+
try {
|
|
34
|
+
const c = (await provider()) || {};
|
|
35
|
+
const optional = (Array.isArray(c.optional) ? c.optional : [])
|
|
36
|
+
.filter((m) => m && typeof m.key === 'string' && m.key)
|
|
37
|
+
.map((m) => ({ key: m.key, label: String(m.label || m.key), summary: String(m.summary || '') }));
|
|
38
|
+
return { core: Array.isArray(c.core) ? c.core.filter((k) => typeof k === 'string') : [], optional };
|
|
39
|
+
} catch (_) {
|
|
40
|
+
return { core: [], optional: [] };
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Can the site afford a call of `extraMicro` right now? → null, or the form reason.
|
|
45
|
+
async function siteBudgetReason(settings, extraMicro) {
|
|
46
|
+
const pending = reservations.siteMicro();
|
|
47
|
+
// Spent is spent (>=), and a call must also fit in what is left (>).
|
|
48
|
+
const over = (spent, cap) => spent + pending >= cap || spent + pending + extraMicro > cap;
|
|
49
|
+
if (over(await db.siteSpendMicro('day'), settings.dailyBudgetMicro)) return 'daily_budget';
|
|
50
|
+
if (over(await db.siteSpendMicro('month'), settings.monthlyBudgetMicro)) return 'monthly_budget';
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
module.exports = { reservations, salt, productName, moduleCatalog, siteBudgetReason };
|