@bongos/core 1.19.409 → 1.19.410
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 +35 -30
- package/clients/bongos-client/README.md +1 -1
- package/clients/bongos-client/bongos-client.global.js +4 -0
- package/clients/bongos-client/index.cjs +4 -0
- package/clients/bongos-client/index.d.ts +5 -0
- package/clients/bongos-client/index.mjs +4 -0
- package/docs/api/openapi.json +122 -3
- package/docs/api-reference.md +4 -2
- package/docs/copy-inventory.md +43 -36
- package/docs/copy-registry.json +122 -39
- package/migrations/core_229_goals_accepting_requests.sql +37 -0
- package/modules/dev-box/app/src/vendor/bongos-client.cjs +4 -0
- package/modules/hall-ui/public/goals-page.js +26 -2
- package/modules/hall-ui/public/goals-render.js +35 -0
- package/modules/lifecycle/db-goals.js +22 -1
- package/modules/lifecycle/db.js +4 -1
- package/modules/lifecycle/goal-edits.js +40 -0
- package/modules/lifecycle/routes/goal-route-authz.js +51 -1
- package/modules/lifecycle/routes/goals.js +46 -1
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/src/bongos/route-rank-check.js +6 -0
- package/src/module-api.js +3 -1
- package/tests/goal_membership_requests.mjs +154 -1
- package/tests/prose_edits.mjs +8 -4
package/docs/copy-registry.json
CHANGED
|
@@ -3,17 +3,17 @@
|
|
|
3
3
|
"generator": "scripts/gds/copy-inventory.js",
|
|
4
4
|
"goal": 1000074,
|
|
5
5
|
"counts": {
|
|
6
|
-
"strings":
|
|
7
|
-
"unique_ids":
|
|
8
|
-
"certain":
|
|
6
|
+
"strings": 1542,
|
|
7
|
+
"unique_ids": 1339,
|
|
8
|
+
"certain": 1542,
|
|
9
9
|
"heuristic": 0,
|
|
10
|
-
"duplicate_ids":
|
|
10
|
+
"duplicate_ids": 156
|
|
11
11
|
},
|
|
12
12
|
"surfaces": {
|
|
13
13
|
"builders-hall": {
|
|
14
14
|
"at": "modules/hall-ui/public",
|
|
15
15
|
"files": 71,
|
|
16
|
-
"strings":
|
|
16
|
+
"strings": 1137
|
|
17
17
|
},
|
|
18
18
|
"status-dashboard": {
|
|
19
19
|
"at": "modules/status-ui/public",
|
|
@@ -955,6 +955,26 @@
|
|
|
955
955
|
"modules/hall-ui/public/work.js:1014"
|
|
956
956
|
]
|
|
957
957
|
},
|
|
958
|
+
{
|
|
959
|
+
"id": "0bc1d1470e22",
|
|
960
|
+
"surface": "builders-hall",
|
|
961
|
+
"text": "Only an open goal can be managed.",
|
|
962
|
+
"occurrences": 2,
|
|
963
|
+
"at": [
|
|
964
|
+
"modules/hall-ui/public/goals-render.js:976",
|
|
965
|
+
"modules/hall-ui/public/goals-render.js:992"
|
|
966
|
+
]
|
|
967
|
+
},
|
|
968
|
+
{
|
|
969
|
+
"id": "fa818ee444b4",
|
|
970
|
+
"surface": "builders-hall",
|
|
971
|
+
"text": "Only this goal's owner or a manager (or an Archon) may do this.",
|
|
972
|
+
"occurrences": 2,
|
|
973
|
+
"at": [
|
|
974
|
+
"modules/hall-ui/public/goals-render.js:975",
|
|
975
|
+
"modules/hall-ui/public/goals-render.js:991"
|
|
976
|
+
]
|
|
977
|
+
},
|
|
958
978
|
{
|
|
959
979
|
"id": "6912678b962b",
|
|
960
980
|
"surface": "builders-hall",
|
|
@@ -1291,8 +1311,8 @@
|
|
|
1291
1311
|
"text": "This goal is not open.",
|
|
1292
1312
|
"occurrences": 2,
|
|
1293
1313
|
"at": [
|
|
1294
|
-
"modules/hall-ui/public/goals-render.js:
|
|
1295
|
-
"modules/hall-ui/public/goals-render.js:
|
|
1314
|
+
"modules/hall-ui/public/goals-render.js:946",
|
|
1315
|
+
"modules/hall-ui/public/goals-render.js:962"
|
|
1296
1316
|
]
|
|
1297
1317
|
},
|
|
1298
1318
|
{
|
|
@@ -1812,7 +1832,7 @@
|
|
|
1812
1832
|
"surface": "builders-hall",
|
|
1813
1833
|
"text": "+ Invite",
|
|
1814
1834
|
"file": "modules/hall-ui/public/goals-render.js",
|
|
1815
|
-
"line":
|
|
1835
|
+
"line": 894,
|
|
1816
1836
|
"origin": "js-markup",
|
|
1817
1837
|
"confidence": "certain"
|
|
1818
1838
|
},
|
|
@@ -1992,7 +2012,7 @@
|
|
|
1992
2012
|
"surface": "builders-hall",
|
|
1993
2013
|
"text": "A protected-scope goal requires a Metic+ member.",
|
|
1994
2014
|
"file": "modules/hall-ui/public/goals-render.js",
|
|
1995
|
-
"line":
|
|
2015
|
+
"line": 944,
|
|
1996
2016
|
"origin": "js-notice",
|
|
1997
2017
|
"confidence": "certain"
|
|
1998
2018
|
},
|
|
@@ -2451,7 +2471,7 @@
|
|
|
2451
2471
|
"surface": "builders-hall",
|
|
2452
2472
|
"text": "Awaiting the owner/manager's approval",
|
|
2453
2473
|
"file": "modules/hall-ui/public/goals-render.js",
|
|
2454
|
-
"line":
|
|
2474
|
+
"line": 788,
|
|
2455
2475
|
"origin": "js-markup",
|
|
2456
2476
|
"confidence": "certain"
|
|
2457
2477
|
},
|
|
@@ -3319,6 +3339,15 @@
|
|
|
3319
3339
|
"origin": "js-notice",
|
|
3320
3340
|
"confidence": "certain"
|
|
3321
3341
|
},
|
|
3342
|
+
{
|
|
3343
|
+
"id": "1ef1efc15b6c",
|
|
3344
|
+
"surface": "builders-hall",
|
|
3345
|
+
"text": "Could not change that just now.",
|
|
3346
|
+
"file": "modules/hall-ui/public/goals-render.js",
|
|
3347
|
+
"line": 993,
|
|
3348
|
+
"origin": "js-notice",
|
|
3349
|
+
"confidence": "certain"
|
|
3350
|
+
},
|
|
3322
3351
|
{
|
|
3323
3352
|
"id": "78e18ea59b9f",
|
|
3324
3353
|
"surface": "builders-hall",
|
|
@@ -3387,7 +3416,7 @@
|
|
|
3387
3416
|
"surface": "builders-hall",
|
|
3388
3417
|
"text": "Could not invite that builder just now.",
|
|
3389
3418
|
"file": "modules/hall-ui/public/goals-render.js",
|
|
3390
|
-
"line":
|
|
3419
|
+
"line": 947,
|
|
3391
3420
|
"origin": "js-notice",
|
|
3392
3421
|
"confidence": "certain"
|
|
3393
3422
|
},
|
|
@@ -3864,7 +3893,7 @@
|
|
|
3864
3893
|
"surface": "builders-hall",
|
|
3865
3894
|
"text": "Could not send the request just now.",
|
|
3866
3895
|
"file": "modules/hall-ui/public/goals-render.js",
|
|
3867
|
-
"line":
|
|
3896
|
+
"line": 1008,
|
|
3868
3897
|
"origin": "js-notice",
|
|
3869
3898
|
"confidence": "certain"
|
|
3870
3899
|
},
|
|
@@ -3900,7 +3929,7 @@
|
|
|
3900
3929
|
"surface": "builders-hall",
|
|
3901
3930
|
"text": "Could not update visibility just now.",
|
|
3902
3931
|
"file": "modules/hall-ui/public/goals-render.js",
|
|
3903
|
-
"line":
|
|
3932
|
+
"line": 977,
|
|
3904
3933
|
"origin": "js-notice",
|
|
3905
3934
|
"confidence": "certain"
|
|
3906
3935
|
},
|
|
@@ -3936,7 +3965,7 @@
|
|
|
3936
3965
|
"surface": "builders-hall",
|
|
3937
3966
|
"text": "Could not {…} just now.",
|
|
3938
3967
|
"file": "modules/hall-ui/public/goals-render.js",
|
|
3939
|
-
"line":
|
|
3968
|
+
"line": 963,
|
|
3940
3969
|
"origin": "js-notice",
|
|
3941
3970
|
"confidence": "certain"
|
|
3942
3971
|
},
|
|
@@ -4449,7 +4478,7 @@
|
|
|
4449
4478
|
"surface": "builders-hall",
|
|
4450
4479
|
"text": "Everyone is already a member",
|
|
4451
4480
|
"file": "modules/hall-ui/public/goals-render.js",
|
|
4452
|
-
"line":
|
|
4481
|
+
"line": 910,
|
|
4453
4482
|
"origin": "js-markup",
|
|
4454
4483
|
"confidence": "certain"
|
|
4455
4484
|
},
|
|
@@ -4764,7 +4793,7 @@
|
|
|
4764
4793
|
"surface": "builders-hall",
|
|
4765
4794
|
"text": "Goals could not be loaded. Refresh to try again.",
|
|
4766
4795
|
"file": "modules/hall-ui/public/goals-page.js",
|
|
4767
|
-
"line":
|
|
4796
|
+
"line": 889,
|
|
4768
4797
|
"origin": "js-text-assign",
|
|
4769
4798
|
"confidence": "certain"
|
|
4770
4799
|
},
|
|
@@ -5182,6 +5211,15 @@
|
|
|
5182
5211
|
"origin": "html-text",
|
|
5183
5212
|
"confidence": "certain"
|
|
5184
5213
|
},
|
|
5214
|
+
{
|
|
5215
|
+
"id": "dad3388b49c9",
|
|
5216
|
+
"surface": "builders-hall",
|
|
5217
|
+
"text": "Invitation rescinded.",
|
|
5218
|
+
"file": "modules/hall-ui/public/goals-page.js",
|
|
5219
|
+
"line": 692,
|
|
5220
|
+
"origin": "js-notice",
|
|
5221
|
+
"confidence": "certain"
|
|
5222
|
+
},
|
|
5185
5223
|
{
|
|
5186
5224
|
"id": "24f9e88c21f6",
|
|
5187
5225
|
"surface": "builders-hall",
|
|
@@ -5196,7 +5234,7 @@
|
|
|
5196
5234
|
"surface": "builders-hall",
|
|
5197
5235
|
"text": "Invited.",
|
|
5198
5236
|
"file": "modules/hall-ui/public/goals-render.js",
|
|
5199
|
-
"line":
|
|
5237
|
+
"line": 936,
|
|
5200
5238
|
"origin": "js-notice",
|
|
5201
5239
|
"confidence": "certain"
|
|
5202
5240
|
},
|
|
@@ -5259,7 +5297,7 @@
|
|
|
5259
5297
|
"surface": "builders-hall",
|
|
5260
5298
|
"text": "Join goal",
|
|
5261
5299
|
"file": "modules/hall-ui/public/goals-render.js",
|
|
5262
|
-
"line":
|
|
5300
|
+
"line": 798,
|
|
5263
5301
|
"origin": "js-markup",
|
|
5264
5302
|
"confidence": "certain"
|
|
5265
5303
|
},
|
|
@@ -5277,7 +5315,7 @@
|
|
|
5277
5315
|
"surface": "builders-hall",
|
|
5278
5316
|
"text": "Join requests",
|
|
5279
5317
|
"file": "modules/hall-ui/public/goals-render.js",
|
|
5280
|
-
"line":
|
|
5318
|
+
"line": 1047,
|
|
5281
5319
|
"origin": "js-markup",
|
|
5282
5320
|
"confidence": "certain"
|
|
5283
5321
|
},
|
|
@@ -5439,7 +5477,7 @@
|
|
|
5439
5477
|
"surface": "builders-hall",
|
|
5440
5478
|
"text": "Leave goal",
|
|
5441
5479
|
"file": "modules/hall-ui/public/goals-render.js",
|
|
5442
|
-
"line":
|
|
5480
|
+
"line": 785,
|
|
5443
5481
|
"origin": "js-markup",
|
|
5444
5482
|
"confidence": "certain"
|
|
5445
5483
|
},
|
|
@@ -6334,6 +6372,15 @@
|
|
|
6334
6372
|
"origin": "html-text",
|
|
6335
6373
|
"confidence": "certain"
|
|
6336
6374
|
},
|
|
6375
|
+
{
|
|
6376
|
+
"id": "a290f6c14df9",
|
|
6377
|
+
"surface": "builders-hall",
|
|
6378
|
+
"text": "Not taking requests",
|
|
6379
|
+
"file": "modules/hall-ui/public/goals-render.js",
|
|
6380
|
+
"line": 793,
|
|
6381
|
+
"origin": "js-markup",
|
|
6382
|
+
"confidence": "certain"
|
|
6383
|
+
},
|
|
6337
6384
|
{
|
|
6338
6385
|
"id": "19adac0efed1",
|
|
6339
6386
|
"surface": "builders-hall",
|
|
@@ -6501,7 +6548,16 @@
|
|
|
6501
6548
|
"surface": "builders-hall",
|
|
6502
6549
|
"text": "Only an open goal can be managed.",
|
|
6503
6550
|
"file": "modules/hall-ui/public/goals-render.js",
|
|
6504
|
-
"line":
|
|
6551
|
+
"line": 976,
|
|
6552
|
+
"origin": "js-notice",
|
|
6553
|
+
"confidence": "certain"
|
|
6554
|
+
},
|
|
6555
|
+
{
|
|
6556
|
+
"id": "0bc1d1470e22",
|
|
6557
|
+
"surface": "builders-hall",
|
|
6558
|
+
"text": "Only an open goal can be managed.",
|
|
6559
|
+
"file": "modules/hall-ui/public/goals-render.js",
|
|
6560
|
+
"line": 992,
|
|
6505
6561
|
"origin": "js-notice",
|
|
6506
6562
|
"confidence": "certain"
|
|
6507
6563
|
},
|
|
@@ -6510,7 +6566,16 @@
|
|
|
6510
6566
|
"surface": "builders-hall",
|
|
6511
6567
|
"text": "Only this goal's owner or a manager (or an Archon) may do this.",
|
|
6512
6568
|
"file": "modules/hall-ui/public/goals-render.js",
|
|
6513
|
-
"line":
|
|
6569
|
+
"line": 975,
|
|
6570
|
+
"origin": "js-notice",
|
|
6571
|
+
"confidence": "certain"
|
|
6572
|
+
},
|
|
6573
|
+
{
|
|
6574
|
+
"id": "fa818ee444b4",
|
|
6575
|
+
"surface": "builders-hall",
|
|
6576
|
+
"text": "Only this goal's owner or a manager (or an Archon) may do this.",
|
|
6577
|
+
"file": "modules/hall-ui/public/goals-render.js",
|
|
6578
|
+
"line": 991,
|
|
6514
6579
|
"origin": "js-notice",
|
|
6515
6580
|
"confidence": "certain"
|
|
6516
6581
|
},
|
|
@@ -6519,7 +6584,7 @@
|
|
|
6519
6584
|
"surface": "builders-hall",
|
|
6520
6585
|
"text": "Only this goal's owner or a manager (or an Archon) may invite.",
|
|
6521
6586
|
"file": "modules/hall-ui/public/goals-render.js",
|
|
6522
|
-
"line":
|
|
6587
|
+
"line": 945,
|
|
6523
6588
|
"origin": "js-notice",
|
|
6524
6589
|
"confidence": "certain"
|
|
6525
6590
|
},
|
|
@@ -6780,7 +6845,7 @@
|
|
|
6780
6845
|
"surface": "builders-hall",
|
|
6781
6846
|
"text": "Pending invitations",
|
|
6782
6847
|
"file": "modules/hall-ui/public/goals-render.js",
|
|
6783
|
-
"line":
|
|
6848
|
+
"line": 1048,
|
|
6784
6849
|
"origin": "js-markup",
|
|
6785
6850
|
"confidence": "certain"
|
|
6786
6851
|
},
|
|
@@ -7410,7 +7475,7 @@
|
|
|
7410
7475
|
"surface": "builders-hall",
|
|
7411
7476
|
"text": "Request sent — the owner or a manager will review it.",
|
|
7412
7477
|
"file": "modules/hall-ui/public/goals-render.js",
|
|
7413
|
-
"line":
|
|
7478
|
+
"line": 999,
|
|
7414
7479
|
"origin": "js-notice",
|
|
7415
7480
|
"confidence": "certain"
|
|
7416
7481
|
},
|
|
@@ -7428,7 +7493,7 @@
|
|
|
7428
7493
|
"surface": "builders-hall",
|
|
7429
7494
|
"text": "Request withdrawn.",
|
|
7430
7495
|
"file": "modules/hall-ui/public/goals-render.js",
|
|
7431
|
-
"line":
|
|
7496
|
+
"line": 1015,
|
|
7432
7497
|
"origin": "js-notice",
|
|
7433
7498
|
"confidence": "certain"
|
|
7434
7499
|
},
|
|
@@ -7959,7 +8024,7 @@
|
|
|
7959
8024
|
"surface": "builders-hall",
|
|
7960
8025
|
"text": "Sign in to filter to your goals",
|
|
7961
8026
|
"file": "modules/hall-ui/public/goals-page.js",
|
|
7962
|
-
"line":
|
|
8027
|
+
"line": 866,
|
|
7963
8028
|
"origin": "js-text-assign",
|
|
7964
8029
|
"confidence": "certain"
|
|
7965
8030
|
},
|
|
@@ -8301,7 +8366,7 @@
|
|
|
8301
8366
|
"surface": "builders-hall",
|
|
8302
8367
|
"text": "Tasks could not be loaded.",
|
|
8303
8368
|
"file": "modules/hall-ui/public/goals-render.js",
|
|
8304
|
-
"line":
|
|
8369
|
+
"line": 867,
|
|
8305
8370
|
"origin": "js-markup",
|
|
8306
8371
|
"confidence": "certain"
|
|
8307
8372
|
},
|
|
@@ -8440,6 +8505,15 @@
|
|
|
8440
8505
|
"origin": "js-markup",
|
|
8441
8506
|
"confidence": "certain"
|
|
8442
8507
|
},
|
|
8508
|
+
{
|
|
8509
|
+
"id": "4dd13bc5a35b",
|
|
8510
|
+
"surface": "builders-hall",
|
|
8511
|
+
"text": "The goal's leads have paused applications; they can still invite you",
|
|
8512
|
+
"file": "modules/hall-ui/public/goals-render.js",
|
|
8513
|
+
"line": 793,
|
|
8514
|
+
"origin": "js-markup",
|
|
8515
|
+
"confidence": "certain"
|
|
8516
|
+
},
|
|
8443
8517
|
{
|
|
8444
8518
|
"id": "797f02fa8295",
|
|
8445
8519
|
"surface": "builders-hall",
|
|
@@ -8733,7 +8807,7 @@
|
|
|
8733
8807
|
"surface": "builders-hall",
|
|
8734
8808
|
"text": "This goal is Archon-mediated — request to join instead.",
|
|
8735
8809
|
"file": "modules/hall-ui/public/goals-render.js",
|
|
8736
|
-
"line":
|
|
8810
|
+
"line": 959,
|
|
8737
8811
|
"origin": "js-notice",
|
|
8738
8812
|
"confidence": "certain"
|
|
8739
8813
|
},
|
|
@@ -8751,7 +8825,7 @@
|
|
|
8751
8825
|
"surface": "builders-hall",
|
|
8752
8826
|
"text": "This goal is not open.",
|
|
8753
8827
|
"file": "modules/hall-ui/public/goals-render.js",
|
|
8754
|
-
"line":
|
|
8828
|
+
"line": 946,
|
|
8755
8829
|
"origin": "js-notice",
|
|
8756
8830
|
"confidence": "certain"
|
|
8757
8831
|
},
|
|
@@ -8760,7 +8834,7 @@
|
|
|
8760
8834
|
"surface": "builders-hall",
|
|
8761
8835
|
"text": "This goal is not open.",
|
|
8762
8836
|
"file": "modules/hall-ui/public/goals-render.js",
|
|
8763
|
-
"line":
|
|
8837
|
+
"line": 962,
|
|
8764
8838
|
"origin": "js-notice",
|
|
8765
8839
|
"confidence": "certain"
|
|
8766
8840
|
},
|
|
@@ -8769,7 +8843,7 @@
|
|
|
8769
8843
|
"surface": "builders-hall",
|
|
8770
8844
|
"text": "This goal is open — joining directly instead.",
|
|
8771
8845
|
"file": "modules/hall-ui/public/goals-render.js",
|
|
8772
|
-
"line":
|
|
8846
|
+
"line": 1006,
|
|
8773
8847
|
"origin": "js-notice",
|
|
8774
8848
|
"confidence": "certain"
|
|
8775
8849
|
},
|
|
@@ -8778,7 +8852,7 @@
|
|
|
8778
8852
|
"surface": "builders-hall",
|
|
8779
8853
|
"text": "This goal is private — request to join instead.",
|
|
8780
8854
|
"file": "modules/hall-ui/public/goals-render.js",
|
|
8781
|
-
"line":
|
|
8855
|
+
"line": 960,
|
|
8782
8856
|
"origin": "js-notice",
|
|
8783
8857
|
"confidence": "certain"
|
|
8784
8858
|
},
|
|
@@ -8787,7 +8861,16 @@
|
|
|
8787
8861
|
"surface": "builders-hall",
|
|
8788
8862
|
"text": "This goal is scoped to a protected module — only an Archon may add members.",
|
|
8789
8863
|
"file": "modules/hall-ui/public/goals-render.js",
|
|
8790
|
-
"line":
|
|
8864
|
+
"line": 943,
|
|
8865
|
+
"origin": "js-notice",
|
|
8866
|
+
"confidence": "certain"
|
|
8867
|
+
},
|
|
8868
|
+
{
|
|
8869
|
+
"id": "ba404d3207f7",
|
|
8870
|
+
"surface": "builders-hall",
|
|
8871
|
+
"text": "This goal isn't taking requests right now.",
|
|
8872
|
+
"file": "modules/hall-ui/public/goals-render.js",
|
|
8873
|
+
"line": 1007,
|
|
8791
8874
|
"origin": "js-notice",
|
|
8792
8875
|
"confidence": "certain"
|
|
8793
8876
|
},
|
|
@@ -9399,7 +9482,7 @@
|
|
|
9399
9482
|
"surface": "builders-hall",
|
|
9400
9483
|
"text": "You already have a pending request or invitation for this goal.",
|
|
9401
9484
|
"file": "modules/hall-ui/public/goals-render.js",
|
|
9402
|
-
"line":
|
|
9485
|
+
"line": 1004,
|
|
9403
9486
|
"origin": "js-notice",
|
|
9404
9487
|
"confidence": "certain"
|
|
9405
9488
|
},
|
|
@@ -9408,7 +9491,7 @@
|
|
|
9408
9491
|
"surface": "builders-hall",
|
|
9409
9492
|
"text": "You are already a member of this goal.",
|
|
9410
9493
|
"file": "modules/hall-ui/public/goals-render.js",
|
|
9411
|
-
"line":
|
|
9494
|
+
"line": 1005,
|
|
9412
9495
|
"origin": "js-notice",
|
|
9413
9496
|
"confidence": "certain"
|
|
9414
9497
|
},
|
|
@@ -9417,7 +9500,7 @@
|
|
|
9417
9500
|
"surface": "builders-hall",
|
|
9418
9501
|
"text": "You are not a member of this goal.",
|
|
9419
9502
|
"file": "modules/hall-ui/public/goals-render.js",
|
|
9420
|
-
"line":
|
|
9503
|
+
"line": 961,
|
|
9421
9504
|
"origin": "js-notice",
|
|
9422
9505
|
"confidence": "certain"
|
|
9423
9506
|
},
|
|
@@ -10317,7 +10400,7 @@
|
|
|
10317
10400
|
"surface": "builders-hall",
|
|
10318
10401
|
"text": "invited — awaiting their response",
|
|
10319
10402
|
"file": "modules/hall-ui/public/goals-render.js",
|
|
10320
|
-
"line":
|
|
10403
|
+
"line": 1039,
|
|
10321
10404
|
"origin": "js-markup",
|
|
10322
10405
|
"confidence": "certain"
|
|
10323
10406
|
},
|
|
@@ -11784,7 +11867,7 @@
|
|
|
11784
11867
|
"surface": "builders-hall",
|
|
11785
11868
|
"text": "🔒 Request to join",
|
|
11786
11869
|
"file": "modules/hall-ui/public/goals-render.js",
|
|
11787
|
-
"line":
|
|
11870
|
+
"line": 795,
|
|
11788
11871
|
"origin": "js-markup",
|
|
11789
11872
|
"confidence": "certain"
|
|
11790
11873
|
},
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
-- core_229_goals_accepting_requests.sql — a private goal can be CLOSED to
|
|
2
|
+
-- join-requests without being closed as a goal (task 1002971, spec
|
|
3
|
+
-- docs/specs/bongos-v1-privacy-and-invites.md D6).
|
|
4
|
+
--
|
|
5
|
+
-- core_188 gave a goal `visibility`, and a private goal has always accepted
|
|
6
|
+
-- join-requests: the only "we're not taking applications" a lead could express
|
|
7
|
+
-- was to archive the goal, which is a different (and destructive) statement.
|
|
8
|
+
-- `accepting_requests` separates the two: a private goal with it FALSE still
|
|
9
|
+
-- runs, still invites, still shows in the list — it just refuses new
|
|
10
|
+
-- join-requests with honest copy instead of queueing asks nobody will answer.
|
|
11
|
+
--
|
|
12
|
+
-- INVITATIONS ARE UNAFFECTED BY DESIGN. Closing applications is about unsolicited
|
|
13
|
+
-- inbound; a lead reaching out to a specific builder is the deliberate act the
|
|
14
|
+
-- flag exists to protect. The flag is likewise MEANINGLESS on a public goal
|
|
15
|
+
-- (self-join needs no request), which is why the toggle renders only on private
|
|
16
|
+
-- goals — the column still exists on every row so the write path needs no
|
|
17
|
+
-- branch, and the refusal gate reads visibility first.
|
|
18
|
+
--
|
|
19
|
+
-- goals is a CORE-owned table (created in 160_goal_tier; ADR 0083 §Decision 5 —
|
|
20
|
+
-- a module migration may touch only its own <key>_ objects), so this lives in
|
|
21
|
+
-- core migrations/, core_-namespaced (ADR 0108 §5: a core migration numbered
|
|
22
|
+
-- above LEGACY_BARE_CORE_MAX=187 must carry the core_ prefix, else the fitness
|
|
23
|
+
-- namespacing check reds the build).
|
|
24
|
+
--
|
|
25
|
+
-- PURELY ADDITIVE + idempotent: DEFAULT true means every existing goal keeps
|
|
26
|
+
-- today's behaviour (a private goal takes requests), NOT NULL is safe because
|
|
27
|
+
-- the default backfills, and IF NOT EXISTS makes a replay a no-op.
|
|
28
|
+
-- Fresh-DB-replay safe; no hard-coded builder ids (learning 1238). migrate.sh
|
|
29
|
+
-- records this file's stem in schema_migrations (the modern 187 pattern — the
|
|
30
|
+
-- file does not self-insert).
|
|
31
|
+
|
|
32
|
+
BEGIN;
|
|
33
|
+
|
|
34
|
+
ALTER TABLE goals
|
|
35
|
+
ADD COLUMN IF NOT EXISTS accepting_requests boolean NOT NULL DEFAULT true;
|
|
36
|
+
|
|
37
|
+
COMMIT;
|
|
@@ -324,6 +324,8 @@ function createClient(opts = {}) {
|
|
|
324
324
|
getGoalsId: (args) => request("GET", "/goals/{id}", { hasBody: false }, args),
|
|
325
325
|
// PATCH /goals/{id} — rank: any-builder — PATCH /goals/:id
|
|
326
326
|
patchGoalsId: (args) => request("PATCH", "/goals/{id}", { hasBody: true }, args),
|
|
327
|
+
// PATCH /goals/{id}/accepting-requests — rank: any-builder — PATCH /goals/:id/accepting-requests
|
|
328
|
+
patchGoalsIdAcceptingRequests: (args) => request("PATCH", "/goals/{id}/accepting-requests", { hasBody: true }, args),
|
|
327
329
|
// POST /goals/{id}/archive — rank: metic+archon — POST /goals/:id/archive
|
|
328
330
|
postGoalsIdArchive: (args) => request("POST", "/goals/{id}/archive", { hasBody: true }, args),
|
|
329
331
|
// PATCH /goals/{id}/category — rank: any-builder — PATCH /goals/:id/category
|
|
@@ -334,6 +336,8 @@ function createClient(opts = {}) {
|
|
|
334
336
|
postGoalsIdConflictsResolve: (args) => request("POST", "/goals/{id}/conflicts/resolve", { hasBody: true }, args),
|
|
335
337
|
// POST /goals/{id}/invitations — rank: any-builder — POST /goals/:id/invitations
|
|
336
338
|
postGoalsIdInvitations: (args) => request("POST", "/goals/{id}/invitations", { hasBody: true }, args),
|
|
339
|
+
// POST /goals/{id}/invitations/{reqId}/rescind — rank: any-builder — POST /goals/:id/invitations/:reqId/rescind
|
|
340
|
+
postGoalsIdInvitationsReqIdRescind: (args) => request("POST", "/goals/{id}/invitations/{reqId}/rescind", { hasBody: true }, args),
|
|
337
341
|
// POST /goals/{id}/invitations/{reqId}/respond — rank: any-builder — POST /goals/:id/invitations/:reqId/respond
|
|
338
342
|
postGoalsIdInvitationsReqIdRespond: (args) => request("POST", "/goals/{id}/invitations/{reqId}/respond", { hasBody: true }, args),
|
|
339
343
|
// POST /goals/{id}/join — rank: any-builder — POST /goals/:id/join
|
|
@@ -678,9 +678,31 @@
|
|
|
678
678
|
}
|
|
679
679
|
}
|
|
680
680
|
|
|
681
|
+
// rescindInvitation (task 1002971) — the goal's own authority takes back an
|
|
682
|
+
// invitation nobody has answered yet, the manager-side mirror of the
|
|
683
|
+
// requester's Withdraw. Shares respondToJoinRequest's in-flight guard so a
|
|
684
|
+
// double-click can't fire two rescinds at one row.
|
|
685
|
+
async function rescindInvitation(goalId, reqId, btn) {
|
|
686
|
+
const key = `rescind:${reqId}`;
|
|
687
|
+
if (pendingActionsPending.has(key)) return;
|
|
688
|
+
pendingActionsPending.add(key);
|
|
689
|
+
if (btn) btn.disabled = true;
|
|
690
|
+
try {
|
|
691
|
+
await postJSON(`${API}/goals/${encodeURIComponent(goalId)}/invitations/${encodeURIComponent(reqId)}/rescind`, {});
|
|
692
|
+
toast('Invitation rescinded.');
|
|
693
|
+
await loadDetail(goalId, { force: true });
|
|
694
|
+
renderDetail(goalId);
|
|
695
|
+
} catch (err) {
|
|
696
|
+
toast((err && err.data && err.data.message) || 'Could not rescind that invitation just now.');
|
|
697
|
+
if (btn) btn.disabled = false;
|
|
698
|
+
} finally {
|
|
699
|
+
pendingActionsPending.delete(key);
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
|
|
681
703
|
// task 1953 — every pending row on THIS goal, rendered for a manager: join
|
|
682
|
-
// requests get Approve/Deny; outstanding
|
|
683
|
-
//
|
|
704
|
+
// requests get Approve/Deny; an outstanding invite the goal sent can be
|
|
705
|
+
// rescinded (task 1002971), and only the invitee can accept/decline theirs.
|
|
684
706
|
|
|
685
707
|
// task 1953 — async membership-queue load, kicked off (fire-and-forget) from
|
|
686
708
|
// renderDetail like loadGoalTasks: my own pending request on this goal (any
|
|
@@ -1060,6 +1082,8 @@
|
|
|
1060
1082
|
if (approveBtn) { respondToJoinRequest(state.current, approveBtn.dataset.approveReq, 'approve', approveBtn); return; }
|
|
1061
1083
|
const denyBtn = e.target.closest('[data-deny-req]');
|
|
1062
1084
|
if (denyBtn) { respondToJoinRequest(state.current, denyBtn.dataset.denyReq, 'deny', denyBtn); return; }
|
|
1085
|
+
const rescindBtn = e.target.closest('[data-rescind-inv]');
|
|
1086
|
+
if (rescindBtn) { rescindInvitation(state.current, rescindBtn.dataset.rescindInv, rescindBtn); return; }
|
|
1063
1087
|
});
|
|
1064
1088
|
window.addEventListener('hashchange', route);
|
|
1065
1089
|
|
|
@@ -772,6 +772,13 @@
|
|
|
772
772
|
const nextVisibility = g.visibility === 'private' ? 'public' : 'private';
|
|
773
773
|
const label = g.visibility === 'private' ? '🔒 Private — make public' : 'Make private';
|
|
774
774
|
parts.push(`<button class="btn-ghost" id="goal-visibility-btn" type="button" data-next-visibility="${escapeHtml(nextVisibility)}">${label}</button>`);
|
|
775
|
+
// task 1002971 (spec D6) — "closed to applications" is a PRIVATE-goal idea
|
|
776
|
+
// only: a public goal is self-join, so the toggle would say nothing there.
|
|
777
|
+
// Closing never touches invitations — a lead can always still invite.
|
|
778
|
+
if (g.visibility === 'private') {
|
|
779
|
+
const closing = g.accepting_requests !== false;
|
|
780
|
+
parts.push(`<button class="btn-ghost" id="goal-accepting-btn" type="button" data-next-accepting="${closing ? 'false' : 'true'}" title="${closing ? 'Stop taking join-requests; you can still invite people' : 'Take join-requests again'}">${closing ? 'Close to requests' : 'Open to requests'}</button>`);
|
|
781
|
+
}
|
|
775
782
|
}
|
|
776
783
|
if (g.status === 'open') {
|
|
777
784
|
if (joined) {
|
|
@@ -780,6 +787,10 @@
|
|
|
780
787
|
if (state.myPendingRequest) {
|
|
781
788
|
parts.push('<span class="member-pill" title="Awaiting the owner/manager\'s approval">Requested</span>');
|
|
782
789
|
parts.push('<button class="btn-ghost" id="goal-withdraw-btn" type="button">Withdraw</button>');
|
|
790
|
+
} else if (g.visibility === 'private' && g.accepting_requests === false) {
|
|
791
|
+
// task 1002971 — say so instead of offering a button the server will
|
|
792
|
+
// refuse; the same honest copy the API answers with.
|
|
793
|
+
parts.push('<span class="member-pill" title="The goal\'s leads have paused applications; they can still invite you">Not taking requests</span>');
|
|
783
794
|
} else {
|
|
784
795
|
parts.push('<button class="btn-ghost" id="goal-request-btn" type="button">🔒 Request to join</button>');
|
|
785
796
|
}
|
|
@@ -791,6 +802,7 @@
|
|
|
791
802
|
$('#goal-join-btn')?.addEventListener('click', () => joinLeave(g.id, 'join'));
|
|
792
803
|
$('#goal-leave-btn')?.addEventListener('click', () => joinLeave(g.id, 'leave'));
|
|
793
804
|
$('#goal-visibility-btn')?.addEventListener('click', (e) => toggleVisibility(g.id, e.currentTarget.dataset.nextVisibility));
|
|
805
|
+
$('#goal-accepting-btn')?.addEventListener('click', (e) => toggleAcceptingRequests(g.id, e.currentTarget.dataset.nextAccepting === 'true'));
|
|
794
806
|
$('#goal-request-btn')?.addEventListener('click', () => requestToJoin(g.id));
|
|
795
807
|
$('#goal-withdraw-btn')?.addEventListener('click', () => withdrawRequest(g.id, state.myPendingRequest && state.myPendingRequest.id));
|
|
796
808
|
}
|
|
@@ -965,6 +977,22 @@
|
|
|
965
977
|
else toast('Could not update visibility just now.');
|
|
966
978
|
}
|
|
967
979
|
}
|
|
980
|
+
// task 1002971 (spec D6) — open/close a PRIVATE goal to join-requests. Closing
|
|
981
|
+
// refuses new asks with honest copy; it never affects invitations, which is why
|
|
982
|
+
// the toast says so out loud rather than reading as "the goal is shut".
|
|
983
|
+
async function toggleAcceptingRequests(goalId, accepting) {
|
|
984
|
+
try {
|
|
985
|
+
await patchJSON(`${API}/goals/${encodeURIComponent(goalId)}/accepting-requests`, { accepting_requests: accepting });
|
|
986
|
+
toast(accepting ? 'This goal is taking join-requests again.' : 'Closed to join-requests — you can still invite people.');
|
|
987
|
+
await loadDetail(goalId, { force: true });
|
|
988
|
+
renderDetail(goalId);
|
|
989
|
+
} catch (err) {
|
|
990
|
+
const code = err?.data?.error;
|
|
991
|
+
if (code === 'not_owner_or_manager') toast('Only this goal\'s owner or a manager (or an Archon) may do this.');
|
|
992
|
+
else if (code === 'goal_not_open') toast('Only an open goal can be managed.');
|
|
993
|
+
else toast('Could not change that just now.');
|
|
994
|
+
}
|
|
995
|
+
}
|
|
968
996
|
async function requestToJoin(goalId) {
|
|
969
997
|
try {
|
|
970
998
|
await postJSON(`${API}/goals/${encodeURIComponent(goalId)}/requests`, {});
|
|
@@ -976,6 +1004,7 @@
|
|
|
976
1004
|
if (code === 'request_pending') toast('You already have a pending request or invitation for this goal.');
|
|
977
1005
|
else if (code === 'already_a_member') toast('You are already a member of this goal.');
|
|
978
1006
|
else if (code === 'goal_is_open') toast('This goal is open — joining directly instead.');
|
|
1007
|
+
else if (code === 'not_accepting_requests') toast('This goal isn\'t taking requests right now.');
|
|
979
1008
|
else toast('Could not send the request just now.');
|
|
980
1009
|
}
|
|
981
1010
|
}
|
|
@@ -1004,9 +1033,15 @@
|
|
|
1004
1033
|
<button class="btn-ghost" type="button" data-deny-req="${escapeHtml(String(r.id))}">Deny</button>
|
|
1005
1034
|
</span>
|
|
1006
1035
|
</li>`;
|
|
1036
|
+
// task 1002971 — an invitation the goal SENT can now be taken back by the
|
|
1037
|
+
// people who sent it (core_188's 'cancelled' = "withdrawn/rescinded by the
|
|
1038
|
+
// opener"); before this the only un-send was asking the invitee to decline.
|
|
1007
1039
|
const inviteLi = (r) => `<li class="pending-row">
|
|
1008
1040
|
<span class="pending-row__who">${escapeHtml(pendingRequestWho(r))}</span>
|
|
1009
1041
|
<span class="pending-row__note">invited — awaiting their response</span>
|
|
1042
|
+
<span class="pending-row__actions">
|
|
1043
|
+
<button class="btn-ghost" type="button" data-rescind-inv="${escapeHtml(String(r.id))}">Rescind</button>
|
|
1044
|
+
</span>
|
|
1010
1045
|
</li>`;
|
|
1011
1046
|
const parts = [];
|
|
1012
1047
|
if (requests.length) parts.push(`<div class="pending-group"><h3 class="pending-group__h">Join requests<span class="count-pill">${requests.length}</span></h3><ul class="pending-list">${requests.map(requestLi).join('')}</ul></div>`);
|
|
@@ -32,7 +32,7 @@ const { deriveRequiredRank, highestRank } = require('./db-rank-authz.js');
|
|
|
32
32
|
// Shared column list so every goal read/return shapes a row identically.
|
|
33
33
|
|
|
34
34
|
const GOAL_COLS =
|
|
35
|
-
'id, version_id, title, subtitle, description, scope_modules, status, visibility, created_by, succeeded_by_goal_id, sort_order, category_id, created_at, updated_at';
|
|
35
|
+
'id, version_id, title, subtitle, description, scope_modules, status, visibility, accepting_requests, created_by, succeeded_by_goal_id, sort_order, category_id, created_at, updated_at';
|
|
36
36
|
|
|
37
37
|
// Shared column list for a goal_membership_requests row (task 1951 / ADR 0112) —
|
|
38
38
|
// the invite / join-request queue behind private goals. Every helper below shapes
|
|
@@ -567,6 +567,26 @@ async function setGoalVisibility({ goalId, visibility }, deps = {}) {
|
|
|
567
567
|
return rows[0] ?? null;
|
|
568
568
|
}
|
|
569
569
|
|
|
570
|
+
// setGoalAcceptingRequests — open or close a PRIVATE goal to new join-requests
|
|
571
|
+
// (task 1002971, spec D6). false = closed: the request path refuses with honest
|
|
572
|
+
// copy instead of queueing asks nobody will answer; invitations keep working, so
|
|
573
|
+
// a lead can still reach out to a specific builder. Meaningless on a public goal
|
|
574
|
+
// (self-join needs no request) — the column exists on every row, and the refusal
|
|
575
|
+
// gate is what reads visibility. Bumps updated_at. Returns the updated goal row,
|
|
576
|
+
// or null for an unknown id. The route gates WHO may call this
|
|
577
|
+
// (authorizeGoalManagement: owner|manager|Archon); this helper just writes.
|
|
578
|
+
async function setGoalAcceptingRequests({ goalId, acceptingRequests }, deps = {}) {
|
|
579
|
+
const activePool = (deps.pool && process.env.NODE_ENV === 'test') ? deps.pool : pool;
|
|
580
|
+
const { rows } = await activePool.query(
|
|
581
|
+
`UPDATE goals
|
|
582
|
+
SET accepting_requests = $2, updated_at = now()
|
|
583
|
+
WHERE id = $1
|
|
584
|
+
RETURNING ${GOAL_COLS}`,
|
|
585
|
+
[goalId, acceptingRequests]
|
|
586
|
+
);
|
|
587
|
+
return rows[0] ?? null;
|
|
588
|
+
}
|
|
589
|
+
|
|
570
590
|
// createMembershipRequest — open a pending invite (kind='invite', a manager asks
|
|
571
591
|
// builder_id in) or join-request (kind='request', the builder asks to join). The
|
|
572
592
|
// partial-unique index (one pending row per goal+builder) means a duplicate ask
|
|
@@ -758,6 +778,7 @@ module.exports = {
|
|
|
758
778
|
setGoalMembershipKind,
|
|
759
779
|
setGoalStatus,
|
|
760
780
|
setGoalSuccessor,
|
|
781
|
+
setGoalAcceptingRequests,
|
|
761
782
|
setGoalVisibility,
|
|
762
783
|
transferGoalOwnership,
|
|
763
784
|
};
|