@saluzi/saluzi-edu 0.2.13 → 0.2.14
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/dist/cli.js +48 -50
- package/dist/rcs-web/assets/{Dashboard-YYwDrKTN.js → Dashboard-BaViKnN5.js} +1 -1
- package/dist/rcs-web/assets/{Join-DKCP5X6X.js → Join-CDMmk1do.js} +1 -1
- package/{packages/remote-control-server/web/dist/assets/Login-0VGZs85I.js → dist/rcs-web/assets/Login-Ch1UCRmx.js} +1 -1
- package/{packages/remote-control-server/web/dist/assets/SessionDetail-DmK-DfBQ.js → dist/rcs-web/assets/SessionDetail-CgQsIF4E.js} +1 -1
- package/dist/rcs-web/assets/{Setup-C0cjxXMt.js → Setup-pGFlgcpn.js} +1 -1
- package/dist/rcs-web/assets/{ShareLanding-DUZrreJ7.js → ShareLanding-BLDP5vrM.js} +1 -1
- package/dist/rcs-web/assets/{TeamCreate-B8ZV6EdY.js → TeamCreate-Dn4BSF1C.js} +1 -1
- package/dist/rcs-web/assets/{TeamDetail-DBAsJ__i.js → TeamDetail-B4og5bFH.js} +1 -1
- package/dist/rcs-web/assets/{TeamList-C-Hte4nV.js → TeamList-BgDk6TT_.js} +1 -1
- package/dist/rcs-web/assets/{TeamSettings-CNVwYwcp.js → TeamSettings-B33f0VFL.js} +1 -1
- package/dist/rcs-web/assets/{UserSettings-DRdz9kYE.js → UserSettings-DVV1ABE0.js} +1 -1
- package/{packages/remote-control-server/web/dist/assets/arc-CJxirXEQ.js → dist/rcs-web/assets/arc-D0nOPOqN.js} +1 -1
- package/dist/rcs-web/assets/{architectureDiagram-3BPJPVTR-BZvIHrLA.js → architectureDiagram-3BPJPVTR-Bk2goLe-.js} +1 -1
- package/dist/rcs-web/assets/{blockDiagram-GPEHLZMM-3p0y3Ija.js → blockDiagram-GPEHLZMM-CsH6uwxc.js} +1 -1
- package/dist/rcs-web/assets/{c4Diagram-AAUBKEIU-Bmz9A1wn.js → c4Diagram-AAUBKEIU-BkizspAZ.js} +1 -1
- package/dist/rcs-web/assets/channel-D6Two4o2.js +1 -0
- package/dist/rcs-web/assets/{chunk-2J33WTMH-B8gQz22j.js → chunk-2J33WTMH-C1wmhoKQ.js} +1 -1
- package/dist/rcs-web/assets/{chunk-4BX2VUAB-CgLEZsTU.js → chunk-4BX2VUAB-CClS7say.js} +1 -1
- package/dist/rcs-web/assets/{chunk-55IACEB6-0mdE_-IS.js → chunk-55IACEB6-Dx1OjjEl.js} +1 -1
- package/{packages/remote-control-server/web/dist/assets/chunk-727SXJPM-DdtjnIHR.js → dist/rcs-web/assets/chunk-727SXJPM-DAX-wriv.js} +1 -1
- package/{packages/remote-control-server/web/dist/assets/chunk-AQP2D5EJ-BtwFPk50.js → dist/rcs-web/assets/chunk-AQP2D5EJ-DS0ZxUTY.js} +1 -1
- package/dist/rcs-web/assets/{chunk-FMBD7UC4-BcO9mQ0P.js → chunk-FMBD7UC4-CnEQFdeK.js} +1 -1
- package/dist/rcs-web/assets/{chunk-ND2GUHAM-BvRq13S_.js → chunk-ND2GUHAM-CDsknXl5.js} +1 -1
- package/dist/rcs-web/assets/{chunk-QZHKN3VN-D7GHkPpq.js → chunk-QZHKN3VN-CHoFWFLU.js} +1 -1
- package/dist/rcs-web/assets/classDiagram-4FO5ZUOK-BFlIXM7X.js +1 -0
- package/dist/rcs-web/assets/classDiagram-v2-Q7XG4LA2-BFlIXM7X.js +1 -0
- package/dist/rcs-web/assets/{code-block-IT6T5CEO-B1p-vO-3.js → code-block-IT6T5CEO-Dg381XPZ.js} +1 -1
- package/{packages/remote-control-server/web/dist/assets/cose-bilkent-S5V4N54A-L0rUZuH5.js → dist/rcs-web/assets/cose-bilkent-S5V4N54A-D4rKemkz.js} +1 -1
- package/dist/rcs-web/assets/{dagre-BM42HDAG-CHGuio22.js → dagre-BM42HDAG-CEziYJ4I.js} +1 -1
- package/dist/rcs-web/assets/{diagram-2AECGRRQ-DIDRyQk8.js → diagram-2AECGRRQ-CVewUt5v.js} +1 -1
- package/dist/rcs-web/assets/{diagram-5GNKFQAL-CNubKb6P.js → diagram-5GNKFQAL-DoR5qnEa.js} +1 -1
- package/dist/rcs-web/assets/{diagram-KO2AKTUF-CzQh664-.js → diagram-KO2AKTUF-Dd0t7r0o.js} +1 -1
- package/dist/rcs-web/assets/{diagram-LMA3HP47-CWBR7-VG.js → diagram-LMA3HP47-Czxf4_ek.js} +1 -1
- package/dist/rcs-web/assets/{diagram-OG6HWLK6-BMHdlbcZ.js → diagram-OG6HWLK6-CVmEsHIK.js} +1 -1
- package/{packages/remote-control-server/web/dist/assets/erDiagram-TEJ5UH35-OgT8dC-K.js → dist/rcs-web/assets/erDiagram-TEJ5UH35-BUiPEvqs.js} +1 -1
- package/{packages/remote-control-server/web/dist/assets/flowDiagram-I6XJVG4X-DRrCY2oB.js → dist/rcs-web/assets/flowDiagram-I6XJVG4X-DuUnrmCq.js} +1 -1
- package/dist/rcs-web/assets/{ganttDiagram-6RSMTGT7-DctpzEKN.js → ganttDiagram-6RSMTGT7-CEg4bmnD.js} +1 -1
- package/dist/rcs-web/assets/{gitGraphDiagram-PVQCEYII-5KpLszm9.js → gitGraphDiagram-PVQCEYII-TCrkArkZ.js} +1 -1
- package/dist/rcs-web/assets/{infoDiagram-5YYISTIA-BAKD_Tt7.js → infoDiagram-5YYISTIA-AbqAkRgB.js} +1 -1
- package/{packages/remote-control-server/web/dist/assets/ishikawaDiagram-YF4QCWOH-VHOPG4Nc.js → dist/rcs-web/assets/ishikawaDiagram-YF4QCWOH-D7hP6ZTe.js} +1 -1
- package/{packages/remote-control-server/web/dist/assets/journeyDiagram-JHISSGLW-BtGih-ik.js → dist/rcs-web/assets/journeyDiagram-JHISSGLW-lgzbZnR_.js} +1 -1
- package/dist/rcs-web/assets/{kanban-definition-UN3LZRKU-BsEGZsD1.js → kanban-definition-UN3LZRKU-DtuPc2km.js} +1 -1
- package/{packages/remote-control-server/web/dist/assets/linear-Dj636PNG.js → dist/rcs-web/assets/linear-CykrAXVD.js} +1 -1
- package/dist/rcs-web/assets/main-yBKWfzqS.js +238 -0
- package/dist/rcs-web/assets/{mermaid-VLURNSYL-DutpHHm9.js → mermaid-VLURNSYL-CIm_M9Fd.js} +4 -4
- package/dist/rcs-web/assets/{mermaid.core-XHHf0pen.js → mermaid.core-DPWsYOtM.js} +5 -5
- package/dist/rcs-web/assets/{mindmap-definition-RKZ34NQL-BBa8V_3g.js → mindmap-definition-RKZ34NQL-DveNryNp.js} +1 -1
- package/dist/rcs-web/assets/{pieDiagram-4H26LBE5-BuNEdo9H.js → pieDiagram-4H26LBE5-B12G_UJC.js} +1 -1
- package/dist/rcs-web/assets/{quadrantDiagram-W4KKPZXB-CsJgyQIN.js → quadrantDiagram-W4KKPZXB-D-TLKxH-.js} +1 -1
- package/dist/rcs-web/assets/{requirementDiagram-4Y6WPE33-DqMJZ914.js → requirementDiagram-4Y6WPE33-BPLGxH6P.js} +1 -1
- package/{packages/remote-control-server/web/dist/assets/sankeyDiagram-5OEKKPKP-CVsz09q2.js → dist/rcs-web/assets/sankeyDiagram-5OEKKPKP-CCIw2zOu.js} +1 -1
- package/{packages/remote-control-server/web/dist/assets/sequenceDiagram-3UESZ5HK-BRp4Wddn.js → dist/rcs-web/assets/sequenceDiagram-3UESZ5HK-BCU0VqSk.js} +1 -1
- package/{packages/remote-control-server/web/dist/assets/stateDiagram-AJRCARHV-S-QqQr-D.js → dist/rcs-web/assets/stateDiagram-AJRCARHV-C2ePZJ4N.js} +1 -1
- package/dist/rcs-web/assets/{stateDiagram-v2-BHNVJYJU-D77KfDr-.js → stateDiagram-v2-BHNVJYJU-aqJyuE4X.js} +1 -1
- package/{packages/remote-control-server/web/dist/assets/timeline-definition-PNZ67QCA-De8bFWnE.js → dist/rcs-web/assets/timeline-definition-PNZ67QCA-CXODIytk.js} +1 -1
- package/dist/rcs-web/assets/{useTeams-CqJOqEy1.js → useTeams-cnFAMG8m.js} +1 -1
- package/dist/rcs-web/assets/{vennDiagram-CIIHVFJN-Dikwrn1L.js → vennDiagram-CIIHVFJN-BuntIwgN.js} +1 -1
- package/dist/rcs-web/assets/{wardleyDiagram-YWT4CUSO-DUzpiV6H.js → wardleyDiagram-YWT4CUSO-DEoH32Tq.js} +1 -1
- package/dist/rcs-web/assets/{workerType-DOQ0AHrq.js → workerType-C-GKof-G.js} +1 -1
- package/dist/rcs-web/assets/{xychartDiagram-2RQKCTM6-OZNbB32D.js → xychartDiagram-2RQKCTM6-DDYJ6G-n.js} +1 -1
- package/dist/rcs-web/index.html +1 -1
- package/package.json +1 -1
- package/packages/remote-control-server/src/__tests__/data-layer-round2.test.ts +12 -11
- package/packages/remote-control-server/src/__tests__/low-priority-fixes.test.ts +178 -0
- package/packages/remote-control-server/src/__tests__/middleware.test.ts +4 -4
- package/packages/remote-control-server/src/__tests__/route-mounting.test.ts +9 -7
- package/packages/remote-control-server/src/__tests__/security-fixes.test.ts +18 -24
- package/packages/remote-control-server/src/__tests__/security-round3.test.ts +5 -1
- package/packages/remote-control-server/src/__tests__/teams.test.ts +7 -0
- package/packages/remote-control-server/src/auth/csrf.ts +1 -3
- package/packages/remote-control-server/src/auth/middleware.ts +13 -4
- package/packages/remote-control-server/src/index.ts +11 -8
- package/packages/remote-control-server/src/routes/v1/environments.ts +12 -9
- package/packages/remote-control-server/src/routes/v1/sessions.ts +1 -1
- package/packages/remote-control-server/src/routes/web/auth-routes.ts +3 -1
- package/packages/remote-control-server/src/routes/web/auth.ts +2 -1
- package/packages/remote-control-server/src/routes/web/sessions.ts +15 -11
- package/packages/remote-control-server/src/routes/web/shares.ts +11 -2
- package/packages/remote-control-server/src/routes/web/teams.ts +6 -9
- package/packages/remote-control-server/src/services/session.ts +1 -12
- package/packages/remote-control-server/src/store.ts +6 -5
- package/packages/remote-control-server/src/types/api.ts +0 -1
- package/packages/remote-control-server/web/dist/assets/{Dashboard-YYwDrKTN.js → Dashboard-BaViKnN5.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{Join-DKCP5X6X.js → Join-CDMmk1do.js} +1 -1
- package/{dist/rcs-web/assets/Login-0VGZs85I.js → packages/remote-control-server/web/dist/assets/Login-Ch1UCRmx.js} +1 -1
- package/{dist/rcs-web/assets/SessionDetail-DmK-DfBQ.js → packages/remote-control-server/web/dist/assets/SessionDetail-CgQsIF4E.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{Setup-C0cjxXMt.js → Setup-pGFlgcpn.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{ShareLanding-DUZrreJ7.js → ShareLanding-BLDP5vrM.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{TeamCreate-B8ZV6EdY.js → TeamCreate-Dn4BSF1C.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{TeamDetail-DBAsJ__i.js → TeamDetail-B4og5bFH.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{TeamList-C-Hte4nV.js → TeamList-BgDk6TT_.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{TeamSettings-CNVwYwcp.js → TeamSettings-B33f0VFL.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{UserSettings-DRdz9kYE.js → UserSettings-DVV1ABE0.js} +1 -1
- package/{dist/rcs-web/assets/arc-CJxirXEQ.js → packages/remote-control-server/web/dist/assets/arc-D0nOPOqN.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{architectureDiagram-3BPJPVTR-BZvIHrLA.js → architectureDiagram-3BPJPVTR-Bk2goLe-.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{blockDiagram-GPEHLZMM-3p0y3Ija.js → blockDiagram-GPEHLZMM-CsH6uwxc.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{c4Diagram-AAUBKEIU-Bmz9A1wn.js → c4Diagram-AAUBKEIU-BkizspAZ.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/channel-D6Two4o2.js +1 -0
- package/packages/remote-control-server/web/dist/assets/{chunk-2J33WTMH-B8gQz22j.js → chunk-2J33WTMH-C1wmhoKQ.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{chunk-4BX2VUAB-CgLEZsTU.js → chunk-4BX2VUAB-CClS7say.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{chunk-55IACEB6-0mdE_-IS.js → chunk-55IACEB6-Dx1OjjEl.js} +1 -1
- package/{dist/rcs-web/assets/chunk-727SXJPM-DdtjnIHR.js → packages/remote-control-server/web/dist/assets/chunk-727SXJPM-DAX-wriv.js} +1 -1
- package/{dist/rcs-web/assets/chunk-AQP2D5EJ-BtwFPk50.js → packages/remote-control-server/web/dist/assets/chunk-AQP2D5EJ-DS0ZxUTY.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{chunk-FMBD7UC4-BcO9mQ0P.js → chunk-FMBD7UC4-CnEQFdeK.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{chunk-ND2GUHAM-BvRq13S_.js → chunk-ND2GUHAM-CDsknXl5.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{chunk-QZHKN3VN-D7GHkPpq.js → chunk-QZHKN3VN-CHoFWFLU.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/classDiagram-4FO5ZUOK-BFlIXM7X.js +1 -0
- package/packages/remote-control-server/web/dist/assets/classDiagram-v2-Q7XG4LA2-BFlIXM7X.js +1 -0
- package/packages/remote-control-server/web/dist/assets/{code-block-IT6T5CEO-B1p-vO-3.js → code-block-IT6T5CEO-Dg381XPZ.js} +1 -1
- package/{dist/rcs-web/assets/cose-bilkent-S5V4N54A-L0rUZuH5.js → packages/remote-control-server/web/dist/assets/cose-bilkent-S5V4N54A-D4rKemkz.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{dagre-BM42HDAG-CHGuio22.js → dagre-BM42HDAG-CEziYJ4I.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{diagram-2AECGRRQ-DIDRyQk8.js → diagram-2AECGRRQ-CVewUt5v.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{diagram-5GNKFQAL-CNubKb6P.js → diagram-5GNKFQAL-DoR5qnEa.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{diagram-KO2AKTUF-CzQh664-.js → diagram-KO2AKTUF-Dd0t7r0o.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{diagram-LMA3HP47-CWBR7-VG.js → diagram-LMA3HP47-Czxf4_ek.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{diagram-OG6HWLK6-BMHdlbcZ.js → diagram-OG6HWLK6-CVmEsHIK.js} +1 -1
- package/{dist/rcs-web/assets/erDiagram-TEJ5UH35-OgT8dC-K.js → packages/remote-control-server/web/dist/assets/erDiagram-TEJ5UH35-BUiPEvqs.js} +1 -1
- package/{dist/rcs-web/assets/flowDiagram-I6XJVG4X-DRrCY2oB.js → packages/remote-control-server/web/dist/assets/flowDiagram-I6XJVG4X-DuUnrmCq.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{ganttDiagram-6RSMTGT7-DctpzEKN.js → ganttDiagram-6RSMTGT7-CEg4bmnD.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{gitGraphDiagram-PVQCEYII-5KpLszm9.js → gitGraphDiagram-PVQCEYII-TCrkArkZ.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{infoDiagram-5YYISTIA-BAKD_Tt7.js → infoDiagram-5YYISTIA-AbqAkRgB.js} +1 -1
- package/{dist/rcs-web/assets/ishikawaDiagram-YF4QCWOH-VHOPG4Nc.js → packages/remote-control-server/web/dist/assets/ishikawaDiagram-YF4QCWOH-D7hP6ZTe.js} +1 -1
- package/{dist/rcs-web/assets/journeyDiagram-JHISSGLW-BtGih-ik.js → packages/remote-control-server/web/dist/assets/journeyDiagram-JHISSGLW-lgzbZnR_.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{kanban-definition-UN3LZRKU-BsEGZsD1.js → kanban-definition-UN3LZRKU-DtuPc2km.js} +1 -1
- package/{dist/rcs-web/assets/linear-Dj636PNG.js → packages/remote-control-server/web/dist/assets/linear-CykrAXVD.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/main-yBKWfzqS.js +238 -0
- package/packages/remote-control-server/web/dist/assets/{mermaid-VLURNSYL-DutpHHm9.js → mermaid-VLURNSYL-CIm_M9Fd.js} +4 -4
- package/packages/remote-control-server/web/dist/assets/{mermaid.core-XHHf0pen.js → mermaid.core-DPWsYOtM.js} +5 -5
- package/packages/remote-control-server/web/dist/assets/{mindmap-definition-RKZ34NQL-BBa8V_3g.js → mindmap-definition-RKZ34NQL-DveNryNp.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{pieDiagram-4H26LBE5-BuNEdo9H.js → pieDiagram-4H26LBE5-B12G_UJC.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{quadrantDiagram-W4KKPZXB-CsJgyQIN.js → quadrantDiagram-W4KKPZXB-D-TLKxH-.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{requirementDiagram-4Y6WPE33-DqMJZ914.js → requirementDiagram-4Y6WPE33-BPLGxH6P.js} +1 -1
- package/{dist/rcs-web/assets/sankeyDiagram-5OEKKPKP-CVsz09q2.js → packages/remote-control-server/web/dist/assets/sankeyDiagram-5OEKKPKP-CCIw2zOu.js} +1 -1
- package/{dist/rcs-web/assets/sequenceDiagram-3UESZ5HK-BRp4Wddn.js → packages/remote-control-server/web/dist/assets/sequenceDiagram-3UESZ5HK-BCU0VqSk.js} +1 -1
- package/{dist/rcs-web/assets/stateDiagram-AJRCARHV-S-QqQr-D.js → packages/remote-control-server/web/dist/assets/stateDiagram-AJRCARHV-C2ePZJ4N.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{stateDiagram-v2-BHNVJYJU-D77KfDr-.js → stateDiagram-v2-BHNVJYJU-aqJyuE4X.js} +1 -1
- package/{dist/rcs-web/assets/timeline-definition-PNZ67QCA-De8bFWnE.js → packages/remote-control-server/web/dist/assets/timeline-definition-PNZ67QCA-CXODIytk.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{useTeams-CqJOqEy1.js → useTeams-cnFAMG8m.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{vennDiagram-CIIHVFJN-Dikwrn1L.js → vennDiagram-CIIHVFJN-BuntIwgN.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{wardleyDiagram-YWT4CUSO-DUzpiV6H.js → wardleyDiagram-YWT4CUSO-DEoH32Tq.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{workerType-DOQ0AHrq.js → workerType-C-GKof-G.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{xychartDiagram-2RQKCTM6-OZNbB32D.js → xychartDiagram-2RQKCTM6-DDYJ6G-n.js} +1 -1
- package/packages/remote-control-server/web/dist/index.html +1 -1
- package/dist/rcs-web/assets/channel-DaI_n8dp.js +0 -1
- package/dist/rcs-web/assets/classDiagram-4FO5ZUOK-pYllpkOq.js +0 -1
- package/dist/rcs-web/assets/classDiagram-v2-Q7XG4LA2-pYllpkOq.js +0 -1
- package/dist/rcs-web/assets/main-CkqtCllF.js +0 -238
- package/packages/remote-control-server/web/dist/assets/channel-DaI_n8dp.js +0 -1
- package/packages/remote-control-server/web/dist/assets/classDiagram-4FO5ZUOK-pYllpkOq.js +0 -1
- package/packages/remote-control-server/web/dist/assets/classDiagram-v2-Q7XG4LA2-pYllpkOq.js +0 -1
- package/packages/remote-control-server/web/dist/assets/main-CkqtCllF.js +0 -238
|
@@ -275,17 +275,17 @@ describe('Security: consumed_at semantics for multi-use invitations', () => {
|
|
|
275
275
|
|
|
276
276
|
// Verify 4 users exist: admin + 3 joined
|
|
277
277
|
const db = getDb!()
|
|
278
|
-
const count = db
|
|
279
|
-
|
|
280
|
-
|
|
278
|
+
const count = db.query('SELECT COUNT(*) as count FROM users').get() as {
|
|
279
|
+
count: number
|
|
280
|
+
}
|
|
281
281
|
expect(count.count).toBe(4)
|
|
282
282
|
|
|
283
283
|
// Verify invitation uses count
|
|
284
|
-
const tokenHash = createHash('sha256')
|
|
285
|
-
.update(inviteToken)
|
|
286
|
-
.digest('hex')
|
|
284
|
+
const tokenHash = createHash('sha256').update(inviteToken).digest('hex')
|
|
287
285
|
const inv = db
|
|
288
|
-
.query(
|
|
286
|
+
.query(
|
|
287
|
+
'SELECT uses, max_uses, consumed_at FROM invitations WHERE token_hash = $hash',
|
|
288
|
+
)
|
|
289
289
|
.get({ $hash: tokenHash }) as {
|
|
290
290
|
uses: number
|
|
291
291
|
max_uses: number
|
|
@@ -493,15 +493,12 @@ describe('Security: CSRF middleware', () => {
|
|
|
493
493
|
app.use('/web/*', csrfCheck)
|
|
494
494
|
app.delete('/web/resource/:id', c => c.json({ ok: true }))
|
|
495
495
|
|
|
496
|
-
const res = await app.request(
|
|
497
|
-
|
|
498
|
-
{
|
|
499
|
-
|
|
500
|
-
headers: {
|
|
501
|
-
Origin: 'http://localhost:3000',
|
|
502
|
-
},
|
|
496
|
+
const res = await app.request('http://localhost:3000/web/resource/abc', {
|
|
497
|
+
method: 'DELETE',
|
|
498
|
+
headers: {
|
|
499
|
+
Origin: 'http://localhost:3000',
|
|
503
500
|
},
|
|
504
|
-
)
|
|
501
|
+
})
|
|
505
502
|
expect(res.status).toBe(200)
|
|
506
503
|
})
|
|
507
504
|
|
|
@@ -511,16 +508,13 @@ describe('Security: CSRF middleware', () => {
|
|
|
511
508
|
app.use('/web/*', csrfCheck)
|
|
512
509
|
app.put('/web/resource/:id', c => c.json({ ok: true }))
|
|
513
510
|
|
|
514
|
-
const res = await app.request(
|
|
515
|
-
|
|
516
|
-
{
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
Origin: 'https://evil.example',
|
|
520
|
-
'Content-Type': 'application/json',
|
|
521
|
-
},
|
|
511
|
+
const res = await app.request('http://localhost:3000/web/resource/abc', {
|
|
512
|
+
method: 'PUT',
|
|
513
|
+
headers: {
|
|
514
|
+
Origin: 'https://evil.example',
|
|
515
|
+
'Content-Type': 'application/json',
|
|
522
516
|
},
|
|
523
|
-
)
|
|
517
|
+
})
|
|
524
518
|
expect(res.status).toBe(403)
|
|
525
519
|
})
|
|
526
520
|
})
|
|
@@ -58,7 +58,11 @@ let issueSessionToken:
|
|
|
58
58
|
) => { accessToken: string; refreshToken: string })
|
|
59
59
|
| undefined
|
|
60
60
|
let resolveSessionToken:
|
|
61
|
-
| ((
|
|
61
|
+
| ((
|
|
62
|
+
token: string,
|
|
63
|
+
db: Database,
|
|
64
|
+
kind?: 'access' | 'refresh',
|
|
65
|
+
) => string | null)
|
|
62
66
|
| undefined
|
|
63
67
|
|
|
64
68
|
try {
|
|
@@ -1479,6 +1479,13 @@ describe('POST /web/environments/:id/transfer', () => {
|
|
|
1479
1479
|
})
|
|
1480
1480
|
|
|
1481
1481
|
test('team admin → 200', async () => {
|
|
1482
|
+
// teamAdmin must also be admin/owner in the target team (security fix)
|
|
1483
|
+
addTeamMember(db, {
|
|
1484
|
+
teamId: targetTeam.id,
|
|
1485
|
+
userId: teamAdmin.id,
|
|
1486
|
+
role: 'admin',
|
|
1487
|
+
addedBy: owner.id,
|
|
1488
|
+
})
|
|
1482
1489
|
const res = await app.request(`/web/environments/${envId}/transfer`, {
|
|
1483
1490
|
method: 'POST',
|
|
1484
1491
|
headers: {
|
|
@@ -40,9 +40,7 @@ export async function csrfCheck(c: Context, next: Next) {
|
|
|
40
40
|
// Support ALLOWED_ORIGINS env variable (comma-separated)
|
|
41
41
|
const envOrigins =
|
|
42
42
|
(c.env?.ALLOWED_ORIGINS as string | undefined) ??
|
|
43
|
-
(typeof process !== 'undefined'
|
|
44
|
-
? process.env.ALLOWED_ORIGINS
|
|
45
|
-
: undefined)
|
|
43
|
+
(typeof process !== 'undefined' ? process.env.ALLOWED_ORIGINS : undefined)
|
|
46
44
|
if (envOrigins) {
|
|
47
45
|
for (const o of envOrigins.split(',')) {
|
|
48
46
|
const trimmed = o.trim()
|
|
@@ -62,8 +62,8 @@ export function extractWebSocketAuthToken(c: Context): string | undefined {
|
|
|
62
62
|
/**
|
|
63
63
|
* Unified authentication middleware — supports two modes:
|
|
64
64
|
*
|
|
65
|
-
* 1. **Token mode** (Web UI): Bearer token resolved via server-side lookup →
|
|
66
|
-
* 2. **API Key mode** (CLI bridge): Valid API key + X-Username header →
|
|
65
|
+
* 1. **Token mode** (Web UI): Bearer token resolved via server-side lookup → userId injected
|
|
66
|
+
* 2. **API Key mode** (CLI bridge): Valid API key + X-Username header → userId injected
|
|
67
67
|
*/
|
|
68
68
|
export async function apiKeyAuth(c: Context, next: Next) {
|
|
69
69
|
const token = extractBearerToken(c)
|
|
@@ -71,7 +71,7 @@ export async function apiKeyAuth(c: Context, next: Next) {
|
|
|
71
71
|
// Try token authentication (Web UI)
|
|
72
72
|
const tokenUsername = resolveToken(token)
|
|
73
73
|
if (tokenUsername) {
|
|
74
|
-
c.set('
|
|
74
|
+
c.set('userId', tokenUsername)
|
|
75
75
|
await next()
|
|
76
76
|
return
|
|
77
77
|
}
|
|
@@ -81,7 +81,7 @@ export async function apiKeyAuth(c: Context, next: Next) {
|
|
|
81
81
|
// Extract username from X-Username header or ?username= query param
|
|
82
82
|
const username = c.req.header('X-Username') || c.req.query('username')
|
|
83
83
|
if (username) {
|
|
84
|
-
c.set('
|
|
84
|
+
c.set('userId', username)
|
|
85
85
|
}
|
|
86
86
|
await next()
|
|
87
87
|
return
|
|
@@ -223,6 +223,15 @@ export async function sessionAuth(c: Context, next: Next) {
|
|
|
223
223
|
}
|
|
224
224
|
} catch (err) {
|
|
225
225
|
console.warn('[sessionAuth] DB resolution failed:', err)
|
|
226
|
+
return c.json(
|
|
227
|
+
{
|
|
228
|
+
error: {
|
|
229
|
+
type: 'service_unavailable',
|
|
230
|
+
message: 'Database unavailable — cannot resolve session token',
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
503,
|
|
234
|
+
)
|
|
226
235
|
}
|
|
227
236
|
}
|
|
228
237
|
|
|
@@ -66,14 +66,17 @@ try {
|
|
|
66
66
|
console.warn('[RCS] Failed to reap expired sessions:', err)
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
const reapInterval = setInterval(
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
69
|
+
const reapInterval = setInterval(
|
|
70
|
+
() => {
|
|
71
|
+
try {
|
|
72
|
+
const db = getDb()
|
|
73
|
+
reapExpiredSessions(db)
|
|
74
|
+
} catch {
|
|
75
|
+
// ignore — DB may not be available
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
60 * 60 * 1000,
|
|
79
|
+
) // every hour
|
|
77
80
|
|
|
78
81
|
if (reapInterval.unref) {
|
|
79
82
|
reapInterval.unref()
|
|
@@ -27,14 +27,14 @@ async function bridgeAuth(c: Context, next: Next) {
|
|
|
27
27
|
if (bearer) {
|
|
28
28
|
// Admin API key
|
|
29
29
|
if (validateApiKey(bearer)) {
|
|
30
|
-
c.set('
|
|
30
|
+
c.set('userId', c.req.header('X-Username') || c.req.query('username'))
|
|
31
31
|
await next()
|
|
32
32
|
return
|
|
33
33
|
}
|
|
34
34
|
// In-memory token
|
|
35
35
|
const username = resolveToken(bearer)
|
|
36
36
|
if (username) {
|
|
37
|
-
c.set('
|
|
37
|
+
c.set('userId', username)
|
|
38
38
|
await next()
|
|
39
39
|
return
|
|
40
40
|
}
|
|
@@ -47,8 +47,9 @@ async function bridgeAuth(c: Context, next: Next) {
|
|
|
47
47
|
await next()
|
|
48
48
|
return
|
|
49
49
|
}
|
|
50
|
-
} catch {
|
|
51
|
-
|
|
50
|
+
} catch (err) {
|
|
51
|
+
console.error('[bridge] DB error during session token resolution:', err)
|
|
52
|
+
return c.json({ error: 'Database unavailable' }, 503)
|
|
52
53
|
}
|
|
53
54
|
}
|
|
54
55
|
// Fall back to apiKeyAuth (handles X-Username + API key from body/header)
|
|
@@ -59,7 +60,7 @@ async function bridgeAuth(c: Context, next: Next) {
|
|
|
59
60
|
app.post('/bridge', acceptCliHeaders, bridgeAuth, async c => {
|
|
60
61
|
const body = await c.req.json()
|
|
61
62
|
const userId = c.get('userId') as string | undefined
|
|
62
|
-
const username =
|
|
63
|
+
const username = userId
|
|
63
64
|
const teamId = c.req.header('X-Team-Id')
|
|
64
65
|
|
|
65
66
|
// Validate team if X-Team-Id is provided
|
|
@@ -102,8 +103,9 @@ app.post('/bridge', acceptCliHeaders, bridgeAuth, async c => {
|
|
|
102
103
|
)
|
|
103
104
|
}
|
|
104
105
|
}
|
|
105
|
-
} catch {
|
|
106
|
-
|
|
106
|
+
} catch (err) {
|
|
107
|
+
console.error('[bridge] DB error during team validation:', err)
|
|
108
|
+
return c.json({ error: 'Database unavailable' }, 503)
|
|
107
109
|
}
|
|
108
110
|
}
|
|
109
111
|
|
|
@@ -116,8 +118,9 @@ app.post('/bridge', acceptCliHeaders, bridgeAuth, async c => {
|
|
|
116
118
|
db.query(
|
|
117
119
|
'INSERT OR IGNORE INTO team_environments (team_id, environment_id) VALUES ($teamId, $envId)',
|
|
118
120
|
).run({ $teamId: teamId, $envId: result.environment_id })
|
|
119
|
-
} catch {
|
|
120
|
-
|
|
121
|
+
} catch (err) {
|
|
122
|
+
console.error('[bridge] DB error during team-environment link:', err)
|
|
123
|
+
return c.json({ error: 'Database unavailable' }, 503)
|
|
121
124
|
}
|
|
122
125
|
}
|
|
123
126
|
|
|
@@ -16,7 +16,7 @@ const app = new Hono()
|
|
|
16
16
|
/** POST /v1/sessions — Create session */
|
|
17
17
|
app.post('/', acceptCliHeaders, apiKeyAuth, async c => {
|
|
18
18
|
const body = await c.req.json()
|
|
19
|
-
const username = c.get('
|
|
19
|
+
const username = c.get('userId')
|
|
20
20
|
const session = createSession({ ...body, username })
|
|
21
21
|
|
|
22
22
|
// Create work item if environment is specified
|
|
@@ -452,7 +452,9 @@ app.post('/join', async c => {
|
|
|
452
452
|
// Re-check invitation state inside the transaction (may have changed).
|
|
453
453
|
// Only check uses >= max_uses — consumed_at is set conditionally below.
|
|
454
454
|
const currentInv = db
|
|
455
|
-
.query(
|
|
455
|
+
.query(
|
|
456
|
+
'SELECT uses, max_uses FROM invitations WHERE token_hash = $hash',
|
|
457
|
+
)
|
|
456
458
|
.get({ $hash: tokenHash }) as { uses: number; max_uses: number } | null
|
|
457
459
|
|
|
458
460
|
if (!currentInv || currentInv.uses >= currentInv.max_uses) {
|
|
@@ -32,18 +32,22 @@ const app = new Hono()
|
|
|
32
32
|
* X-User-Id header for a real user identity. If no valid identity is
|
|
33
33
|
* found, returns null — the session will be orphaned (admin-visible).
|
|
34
34
|
*/
|
|
35
|
-
function resolveBindUserId(
|
|
36
|
-
c
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
35
|
+
function resolveBindUserId(c: import('hono').Context): string | null {
|
|
36
|
+
const userId = c.get('userId')
|
|
37
|
+
if (!userId || userId === SYSTEM_USER_ID) {
|
|
38
|
+
// API key auth — only admin can use X-User-Id to bind on behalf of a user
|
|
39
|
+
const isAdmin = c.get('isAdmin')
|
|
40
|
+
if (!isAdmin) {
|
|
41
|
+
return null // non-admin API key cannot create sessions as another user
|
|
42
|
+
}
|
|
43
|
+
const headerUserId = c.req.header('X-User-Id')
|
|
44
|
+
if (headerUserId && headerUserId !== SYSTEM_USER_ID) {
|
|
45
|
+
console.log(`[audit] API key created session as user ${headerUserId}`)
|
|
46
|
+
return headerUserId
|
|
47
|
+
}
|
|
48
|
+
return null // API key without X-User-Id → orphan session (admin-visible)
|
|
45
49
|
}
|
|
46
|
-
return
|
|
50
|
+
return userId
|
|
47
51
|
}
|
|
48
52
|
|
|
49
53
|
/** POST /web/sessions — Create a session from web UI */
|
|
@@ -14,7 +14,11 @@ interface SessionOwnerRow {
|
|
|
14
14
|
/**
|
|
15
15
|
* Check if a user is a member of a given team.
|
|
16
16
|
*/
|
|
17
|
-
function isTeamMember(
|
|
17
|
+
function isTeamMember(
|
|
18
|
+
userId: string,
|
|
19
|
+
teamId: string,
|
|
20
|
+
db: ReturnType<typeof getDb>,
|
|
21
|
+
): boolean {
|
|
18
22
|
const row = db
|
|
19
23
|
.query(
|
|
20
24
|
'SELECT user_id FROM team_members WHERE team_id = $teamId AND user_id = $userId',
|
|
@@ -379,7 +383,12 @@ app.get(
|
|
|
379
383
|
|
|
380
384
|
if (!isGrantee) {
|
|
381
385
|
return c.json(
|
|
382
|
-
{
|
|
386
|
+
{
|
|
387
|
+
error: {
|
|
388
|
+
type: 'forbidden',
|
|
389
|
+
message: 'Not authorized for this share',
|
|
390
|
+
},
|
|
391
|
+
},
|
|
383
392
|
403,
|
|
384
393
|
)
|
|
385
394
|
}
|
|
@@ -154,10 +154,7 @@ app.post('/teams', withAuth, async c => {
|
|
|
154
154
|
)
|
|
155
155
|
.get() as { id: string } | null
|
|
156
156
|
if (!adminUser) {
|
|
157
|
-
return c.json(
|
|
158
|
-
{ error: 'No admin user available to create team' },
|
|
159
|
-
400,
|
|
160
|
-
)
|
|
157
|
+
return c.json({ error: 'No admin user available to create team' }, 400)
|
|
161
158
|
}
|
|
162
159
|
createdBy = adminUser.id
|
|
163
160
|
}
|
|
@@ -826,11 +823,11 @@ app.post('/environments/:id/transfer', withAuth, async c => {
|
|
|
826
823
|
|
|
827
824
|
// Check caller is owner/admin of the target team
|
|
828
825
|
const targetRole = getTeamRole(toTeamId, user)
|
|
829
|
-
if (
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
)
|
|
826
|
+
if (
|
|
827
|
+
!user.isAdmin &&
|
|
828
|
+
(!targetRole || (targetRole !== 'owner' && targetRole !== 'admin'))
|
|
829
|
+
) {
|
|
830
|
+
return c.json({ error: 'Not authorized in target team' }, 403)
|
|
834
831
|
}
|
|
835
832
|
|
|
836
833
|
// Remove from source team
|
|
@@ -2,7 +2,6 @@ import {
|
|
|
2
2
|
storeCreateSession,
|
|
3
3
|
storeGetSession,
|
|
4
4
|
storeGetEnvironment,
|
|
5
|
-
storeIsSessionOwner,
|
|
6
5
|
storeUpdateSession,
|
|
7
6
|
storeListSessions,
|
|
8
7
|
storeListSessionsByUsername,
|
|
@@ -260,17 +259,7 @@ export function resolveOwnedWebSessionId(
|
|
|
260
259
|
}
|
|
261
260
|
}
|
|
262
261
|
} catch {
|
|
263
|
-
//
|
|
264
|
-
if (storeIsSessionOwner(sessionId, uuid)) {
|
|
265
|
-
return sessionId
|
|
266
|
-
}
|
|
267
|
-
const compatibleCodeSessionId = toCompatibleCodeSessionId(sessionId)
|
|
268
|
-
if (
|
|
269
|
-
compatibleCodeSessionId &&
|
|
270
|
-
storeIsSessionOwner(compatibleCodeSessionId, uuid)
|
|
271
|
-
) {
|
|
272
|
-
return compatibleCodeSessionId
|
|
273
|
-
}
|
|
262
|
+
// DB unavailable — return null rather than falling back to redundant check
|
|
274
263
|
}
|
|
275
264
|
|
|
276
265
|
return null
|
|
@@ -202,9 +202,9 @@ export function storeUpdateEnvironment(
|
|
|
202
202
|
// the environments table has no corresponding columns.
|
|
203
203
|
|
|
204
204
|
if (sets.length > 0) {
|
|
205
|
-
db.query(
|
|
206
|
-
|
|
207
|
-
)
|
|
205
|
+
db.query(`UPDATE environments SET ${sets.join(', ')} WHERE id = $id`).run(
|
|
206
|
+
params,
|
|
207
|
+
)
|
|
208
208
|
}
|
|
209
209
|
} catch (err) {
|
|
210
210
|
console.error('[store] DB write failed in storeUpdateEnvironment:', err)
|
|
@@ -421,7 +421,7 @@ export function storeIsSessionOwner(sessionId: string, uuid: string): boolean {
|
|
|
421
421
|
return !!row
|
|
422
422
|
} catch (err) {
|
|
423
423
|
console.error('[store] DB read failed in storeIsSessionOwner:', err)
|
|
424
|
-
|
|
424
|
+
throw err
|
|
425
425
|
}
|
|
426
426
|
}
|
|
427
427
|
|
|
@@ -439,7 +439,7 @@ export function storeGetSessionOwners(
|
|
|
439
439
|
return new Set(rows.map(r => r.owner_id))
|
|
440
440
|
} catch (err) {
|
|
441
441
|
console.error('[store] DB read failed in storeGetSessionOwners:', err)
|
|
442
|
-
|
|
442
|
+
throw err
|
|
443
443
|
}
|
|
444
444
|
}
|
|
445
445
|
|
|
@@ -478,6 +478,7 @@ export function storeListSessionsByOwnerUuid(uuid: string): SessionRecord[] {
|
|
|
478
478
|
'[store] DB read failed in storeListSessionsByOwnerUuid:',
|
|
479
479
|
err,
|
|
480
480
|
)
|
|
481
|
+
throw err
|
|
481
482
|
}
|
|
482
483
|
|
|
483
484
|
return result
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as e,e as d}from"./vendor-DE_-CLIE.js";import{h as N,B as w,Q as v,I as s,l as k,n as C,o as S,m as _}from"./main-
|
|
1
|
+
import{j as e,e as d}from"./vendor-DE_-CLIE.js";import{h as N,B as w,Q as v,I as s,l as k,n as C,o as S,m as _}from"./main-yBKWfzqS.js";import{g as y,D,a as L,c as E,d as B,b as M}from"./workerType-C-GKof-G.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function T({environments:l,onSelectEnvironment:x}){return!l||l.length===0?e.jsx("div",{className:"rounded-xl border border-border bg-surface-1 p-8 text-center text-text-muted",children:"No active environments"}):e.jsx("div",{className:"space-y-2",children:l.map(a=>{const i=a.worker_type==="acp",c=y(a.worker_type),u=c.fullLabel,t=c.colorClass;return e.jsxs("button",{type:"button",onClick:()=>x==null?void 0:x(a),disabled:i,className:`flex w-full items-center justify-between rounded-xl border border-border bg-surface-1 px-4 py-3 text-left transition-colors ${i?"cursor-default opacity-80":"hover:border-border-light cursor-pointer"}`,children:[e.jsx("div",{className:"flex items-center gap-3",children:e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"font-medium text-text-primary",children:a.machine_name||a.id}),e.jsx("span",{className:`rounded-full px-2 py-0.5 text-xs font-medium ${t}`,children:u})]}),e.jsx("div",{className:"text-sm text-text-muted",children:a.directory||""})]})}),e.jsxs("div",{className:"text-right",children:[e.jsx(N,{status:a.status}),e.jsx("div",{className:"mt-1 text-xs text-text-muted",children:a.branch||""})]})]},a.id)})})}function F({sessions:l,environments:x,onSelect:a,onDelete:i}){if(!l||l.length===0)return e.jsx("div",{className:"rounded-xl border border-border bg-surface-1 p-8 text-center text-text-muted",children:"No sessions"});const c=new Map;for(const t of x??[])t!=null&&t.id&&t.worker_type&&c.set(t.id,t.worker_type);const u=[...l].sort((t,n)=>(n.updated_at||0)-(t.updated_at||0));return e.jsx("div",{className:"space-y-2",children:u.map(t=>e.jsxs("div",{className:"group flex w-full items-center justify-between rounded-xl border border-border bg-surface-1 px-4 py-3 text-left transition-colors hover:border-border-light hover:bg-surface-2",children:[e.jsxs("button",{type:"button",onClick:()=>a(t.id),className:"min-w-0 flex-1 text-left",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"truncate font-medium text-text-primary",children:t.title||t.id}),(()=>{var h;let n=t.source==="acp"?"acp":(h=t.environment)==null?void 0:h.worker_type;!n&&t.environment_id&&(n=c.get(t.environment_id));const p=y(n);return e.jsx("span",{className:`rounded-full px-2 py-0.5 text-xs font-medium ${p.colorClass}`,children:p.fullLabel})})()]}),e.jsx("div",{className:"truncate text-xs text-text-muted",children:t.id})]}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(N,{status:t.status}),e.jsx("span",{className:"text-xs text-text-muted",children:w(t.created_at||t.updated_at)}),i&&e.jsx("button",{type:"button",onClick:n=>{n.stopPropagation(),i(t.id)},className:"rounded p-1 text-text-muted opacity-0 transition-all hover:text-status-error group-hover:opacity-100",title:"Delete session",children:e.jsx("svg",{className:"h-4 w-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})})})]})]},t.id))})}function I({open:l,environments:x,onClose:a,onCreated:i}){v();const[c,u]=d.useState(""),[t,n]=d.useState(""),[p,h]=d.useState("same-dir"),[f,b]=d.useState(""),[o,m]=d.useState(!1);d.useEffect(()=>{l&&(u(""),n(""),h("same-dir"),b(""))},[l]);const g=async()=>{m(!0),b("");try{const r={};c.trim()&&(r.title=c.trim()),t&&(r.environment_id=t),r.spawn_mode=p;const j=await k(r);i(j)}catch(r){b(r instanceof Error?r.message:s("dialog.createFailed"))}finally{m(!1)}};return e.jsx(D,{open:l,onOpenChange:r=>{r||a()},children:e.jsxs(L,{className:"max-w-md rounded-2xl border-border bg-surface-1 p-6 shadow-2xl",children:[e.jsx(E,{children:e.jsx(B,{className:"font-display text-lg font-semibold text-text-primary",children:s("dialog.newSession")})}),e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm text-text-secondary",children:s("dialog.titleOptional")}),e.jsx("input",{type:"text",value:c,onChange:r=>u(r.target.value),placeholder:s("dialog.titlePlaceholder"),className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm text-text-secondary",children:s("dialog.environment")}),e.jsxs("select",{value:t,onChange:r=>n(r.target.value),className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary focus:border-brand focus:outline-none",children:[e.jsx("option",{value:"",children:s("dialog.none")}),x.map(r=>{const j=y(r.worker_type).shortLabel;return e.jsxs("option",{value:r.id,children:[r.machine_name||r.id," (",r.branch||s("dialog.noBranch"),") · ",j]},r.id)})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm text-text-secondary",children:s("dialog.workspaceMode")}),e.jsxs("select",{value:p,onChange:r=>h(r.target.value),className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary focus:border-brand focus:outline-none",children:[e.jsx("option",{value:"same-dir",children:s("dialog.sameDir")}),e.jsx("option",{value:"worktree",children:s("dialog.worktree")})]})]}),f&&e.jsx("div",{className:"text-sm text-status-error",children:f})]}),e.jsxs(M,{children:[e.jsx("button",{onClick:a,className:"rounded-lg border border-border px-4 py-2 text-sm text-text-secondary hover:bg-surface-2 transition-colors",children:s("common.cancel")}),e.jsx("button",{onClick:g,disabled:o,className:"rounded-lg bg-brand px-4 py-2 text-sm font-medium text-white hover:bg-brand-light disabled:opacity-50 transition-colors",children:o?s("common.creating"):s("common.create")})]})]})})}function H({onNavigateSession:l}){v();const[x,a]=d.useState([]),[i,c]=d.useState([]),[u,t]=d.useState(!1),n=d.useCallback(async()=>{try{const[o,m]=await Promise.all([C(),S()]);a(o||[]),c(m||[])}catch(o){console.error("Dashboard render error:",o)}},[]);d.useEffect(()=>{n();const o=setInterval(n,1e4);return()=>clearInterval(o)},[n]);const p=o=>{t(!1),l(o.id)},h=d.useCallback(o=>{},[]),f=d.useCallback(o=>{l(o)},[l]),b=d.useCallback(async o=>{if(window.confirm(s("dashboard.confirmDelete").replace("{id}",o)))try{await _(o),a(m=>m.filter(g=>g.id!==o))}catch(m){alert(m instanceof Error?m.message:s("dashboard.deleteFailed"))}},[]);return e.jsxs("div",{className:"mx-auto max-w-5xl px-4 py-8",children:[e.jsx("h1",{className:"sr-only",children:s("dashboard.title")}),e.jsxs("section",{className:"mb-10",children:[e.jsx("h2",{className:"mb-4 font-display text-lg font-semibold text-text-primary",children:s("dashboard.environments")}),e.jsx(T,{environments:i,onSelectEnvironment:h})]}),e.jsxs("section",{children:[e.jsxs("div",{className:"mb-4 flex items-center justify-between",children:[e.jsx("h2",{className:"font-display text-lg font-semibold text-text-primary",children:s("dashboard.sessions")}),e.jsx("button",{onClick:()=>t(!0),className:"rounded-lg bg-brand px-3 py-1.5 text-sm font-medium text-white hover:bg-brand-light transition-colors",children:s("dashboard.newSession")})]}),e.jsx(F,{sessions:x,environments:i,onSelect:f,onDelete:b})]}),e.jsx(I,{open:u,environments:i,onClose:()=>t(!1),onCreated:p})]})}export{H as Dashboard};
|
package/packages/remote-control-server/web/dist/assets/{Join-DKCP5X6X.js → Join-CDMmk1do.js}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{e as r,j as e}from"./vendor-DE_-CLIE.js";import{N,I as t}from"./main-
|
|
1
|
+
import{e as r,j as e}from"./vendor-DE_-CLIE.js";import{N,I as t}from"./main-yBKWfzqS.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function E({onSuccess:b,onInvalidInvite:l}){const{join:h}=N(),[u,f]=r.useState(""),[d,j]=r.useState(""),[o,w]=r.useState(""),[c,g]=r.useState(""),[m,n]=r.useState(""),[x,p]=r.useState(!1);r.useEffect(()=>{const a=new URLSearchParams(window.location.search).get("invite");a?f(a):l()},[l]);const y=async s=>{if(s.preventDefault(),n(""),o.length<8){n(t("auth.setup.passwordTooShort"));return}if(o!==c){n(t("auth.setup.passwordMismatch"));return}p(!0);try{await h(u,d,o),b()}catch(a){const i=a instanceof Error?a.message:"Join failed";if(i.includes("Invalid invitation")||i.includes("expired")||i.includes("already used")){l();return}n(i)}finally{p(!1)}};return e.jsx("div",{className:"flex min-h-screen items-center justify-center bg-surface-0 px-4",children:e.jsxs("div",{className:"w-full max-w-sm space-y-6",children:[e.jsxs("div",{className:"text-center",children:[e.jsx("h1",{className:"font-display text-2xl font-semibold text-text-primary",children:t("auth.join.title")}),e.jsx("p",{className:"mt-2 text-sm text-text-muted",children:t("auth.join.welcome")}),e.jsx("p",{className:"mt-1 text-sm text-text-muted",children:t("auth.join.description")})]}),e.jsxs("form",{onSubmit:y,className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.join.username")}),e.jsx("input",{type:"text",value:d,onChange:s=>j(s.target.value),required:!0,autoComplete:"username",autoFocus:!0,className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.join.password")}),e.jsx("input",{type:"password",value:o,onChange:s=>w(s.target.value),required:!0,autoComplete:"new-password",className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.join.confirmPassword")}),e.jsx("input",{type:"password",value:c,onChange:s=>g(s.target.value),required:!0,autoComplete:"new-password",className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),m&&e.jsx("p",{className:"text-sm text-status-error",children:m}),e.jsx("button",{type:"submit",disabled:x||!u,className:"w-full rounded-lg bg-brand px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-brand-light disabled:cursor-not-allowed disabled:opacity-50",children:x?t("common.loading"):t("auth.join.submit")})]})]})})}export{E as Join};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{e as r,j as e}from"./vendor-DE_-CLIE.js";import{N as b,I as t}from"./main-
|
|
1
|
+
import{e as r,j as e}from"./vendor-DE_-CLIE.js";import{N as b,I as t}from"./main-yBKWfzqS.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function j({onSuccess:d}){const{login:c}=b(),[a,m]=r.useState(""),[o,x]=r.useState(""),[l,n]=r.useState(""),[i,u]=r.useState(!1),p=async s=>{s.preventDefault(),n(""),u(!0);try{await c(a,o),d()}catch{n(t("auth.login.failed"))}finally{u(!1)}};return e.jsx("div",{className:"flex min-h-screen items-center justify-center bg-surface-0 px-4",children:e.jsxs("div",{className:"w-full max-w-sm space-y-6",children:[e.jsxs("div",{className:"text-center",children:[e.jsx("h1",{className:"font-display text-2xl font-semibold text-text-primary",children:t("auth.login.title")}),e.jsx("p",{className:"mt-2 text-sm text-text-muted",children:t("auth.login.description")})]}),e.jsxs("form",{onSubmit:p,className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.login.username")}),e.jsx("input",{type:"text",value:a,onChange:s=>m(s.target.value),required:!0,autoComplete:"username",autoFocus:!0,className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.login.password")}),e.jsx("input",{type:"password",value:o,onChange:s=>x(s.target.value),required:!0,autoComplete:"current-password",className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),l&&e.jsx("p",{className:"text-sm text-status-error",children:l}),e.jsx("button",{type:"submit",disabled:i,className:"w-full rounded-lg bg-brand px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-brand-light disabled:cursor-not-allowed disabled:opacity-50",children:i?t("common.loading"):t("auth.login.submit")})]})]})})}export{j as Login};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var oe=Object.defineProperty;var ie=(s,t,n)=>t in s?oe(s,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):s[t]=n;var C=(s,t,n)=>ie(s,typeof t!="symbol"?t+"":t,n);import{e as g,j as e}from"./vendor-DE_-CLIE.js";import{x as A,q as le,u as ce,E as de,t as P,r as ue,h as J,B as Y,L as G,j as me,S as xe,z as $,w as D,d as pe,J as he,A as fe,F as ye,Q as ge,K as be,y as je,I as _,m as we,i as X,c as Ne,C as ke,p as ve,G as _e,D as Se,a as Ce}from"./main-
|
|
1
|
+
var oe=Object.defineProperty;var ie=(s,t,n)=>t in s?oe(s,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):s[t]=n;var C=(s,t,n)=>ie(s,typeof t!="symbol"?t+"":t,n);import{e as g,j as e}from"./vendor-DE_-CLIE.js";import{x as A,q as le,u as ce,E as de,t as P,r as ue,h as J,B as Y,L as G,j as me,S as xe,z as $,w as D,d as pe,J as he,A as fe,F as ye,Q as ge,K as be,y as je,I as _,m as we,i as X,c as Ne,C as ke,p as ve,G as _e,D as Se,a as Ce}from"./main-yBKWfzqS.js";import{D as Me,a as Ee,c as $e,d as Ae,g as Te}from"./workerType-C-GKof-G.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";/**
|
|
2
2
|
* @license lucide-react v0.555.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
package/packages/remote-control-server/web/dist/assets/{Setup-C0cjxXMt.js → Setup-pGFlgcpn.js}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{e as r,j as e}from"./vendor-DE_-CLIE.js";import{N as v,I as t}from"./main-
|
|
1
|
+
import{e as r,j as e}from"./vendor-DE_-CLIE.js";import{N as v,I as t}from"./main-yBKWfzqS.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function q({onSuccess:p,onAlreadyDone:b}){const{setup:f}=v(),[n,h]=r.useState(""),[l,y]=r.useState(""),[a,g]=r.useState(""),[d,w]=r.useState(""),[i,o]=r.useState(""),[c,m]=r.useState(!1),j=async s=>{if(s.preventDefault(),o(""),a.length<8){o(t("auth.setup.passwordTooShort"));return}if(a!==d){o(t("auth.setup.passwordMismatch"));return}m(!0);try{await f(n,l,a),p()}catch(x){const u=x instanceof Error?x.message:"Setup failed";if(u.includes("already")||u.includes("409")){b();return}o(u)}finally{m(!1)}};return e.jsx("div",{className:"flex min-h-screen items-center justify-center bg-surface-0 px-4",children:e.jsxs("div",{className:"w-full max-w-sm space-y-6",children:[e.jsxs("div",{className:"text-center",children:[e.jsx("h1",{className:"font-display text-2xl font-semibold text-text-primary",children:t("auth.setup.title")}),e.jsx("p",{className:"mt-2 text-sm text-text-muted",children:t("auth.setup.description")})]}),e.jsxs("form",{onSubmit:j,className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.setup.apiKey")}),e.jsx("input",{type:"password",value:n,onChange:s=>h(s.target.value),required:!0,autoComplete:"off",className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.setup.username")}),e.jsx("input",{type:"text",value:l,onChange:s=>y(s.target.value),required:!0,autoComplete:"username",className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.setup.password")}),e.jsx("input",{type:"password",value:a,onChange:s=>g(s.target.value),required:!0,autoComplete:"new-password",className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.setup.confirmPassword")}),e.jsx("input",{type:"password",value:d,onChange:s=>w(s.target.value),required:!0,autoComplete:"new-password",className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),i&&e.jsx("p",{className:"text-sm text-status-error",children:i}),e.jsx("button",{type:"submit",disabled:c,className:"w-full rounded-lg bg-brand px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-brand-light disabled:cursor-not-allowed disabled:opacity-50",children:c?t("common.loading"):t("auth.setup.submit")})]})]})})}export{q as Setup};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{e as d,j as e}from"./vendor-DE_-CLIE.js";import{s as m,b as h}from"./main-
|
|
1
|
+
import{e as d,j as e}from"./vendor-DE_-CLIE.js";import{s as m,b as h}from"./main-yBKWfzqS.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function j(){const[t,r]=d.useState("loading"),[i,a]=d.useState(""),l=(typeof window<"u"?window.location.pathname:"").match(/\/code\/s\/([^/?]+)/),o=l?l[1]:null;return d.useEffect(()=>{if(!o){r("invalid"),a("Share link is invalid — no token found.");return}if(!o.startsWith("shr_")){r("invalid"),a("Invalid share token format.");return}let n=!1;async function c(){try{const s=await m(o);if(n)return;window.location.href=`/code/${s.id}`}catch(s){if(n)return;s instanceof h?s.status===401&&s.message.toLowerCase().includes("expired")?(r("expired"),a("This share has expired.")):s.status===404?s.message.toLowerCase().includes("session")?(r("not_found"),a("Session not found.")):(r("invalid"),a("Share not found or has been revoked.")):s.status===403?(r("invalid"),a("You do not have permission to access this share.")):(r("error"),a(s.message||"Failed to resolve share.")):(r("error"),a(s instanceof Error?s.message:"Failed to resolve share."))}}return c(),()=>{n=!0}},[o]),d.useEffect(()=>{if(t!=="loading"&&t!=="error"){const n=setTimeout(()=>{window.location.href="/code"},3e3);return()=>clearTimeout(n)}},[t]),t==="loading"?e.jsx("div",{className:"flex h-screen items-center justify-center bg-surface-0 text-text-muted",children:e.jsxs("div",{className:"text-center",children:[e.jsx("div",{className:"animate-spin h-8 w-8 border-2 border-brand border-t-transparent rounded-full mx-auto mb-3"}),e.jsx("p",{children:"Resolving share link..."})]})}):e.jsx("div",{className:"flex h-screen items-center justify-center bg-surface-0 text-text-primary",children:e.jsxs("div",{className:"text-center max-w-md px-4",children:[t==="expired"&&e.jsxs(e.Fragment,{children:[e.jsx("h2",{className:"font-display text-xl font-semibold mb-2",children:"Share Expired"}),e.jsx("p",{className:"text-text-muted mb-4",children:i||"This share has expired."})]}),t==="invalid"&&e.jsxs(e.Fragment,{children:[e.jsx("h2",{className:"font-display text-xl font-semibold mb-2",children:"Invalid Share"}),e.jsx("p",{className:"text-text-muted mb-4",children:i||"This share link is invalid or has been revoked."})]}),t==="not_found"&&e.jsxs(e.Fragment,{children:[e.jsx("h2",{className:"font-display text-xl font-semibold mb-2",children:"Not Found"}),e.jsx("p",{className:"text-text-muted mb-4",children:i||"The session could not be found."})]}),t==="error"&&e.jsxs(e.Fragment,{children:[e.jsx("h2",{className:"font-display text-xl font-semibold mb-2",children:"Error"}),e.jsx("p",{className:"text-status-error mb-4",children:i})]}),e.jsx("a",{href:"/code",className:"text-brand hover:underline",children:"← Back to Dashboard"})]})})}export{j as ShareLanding};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{e as a,j as e}from"./vendor-DE_-CLIE.js";import{u as f}from"./useTeams-
|
|
1
|
+
import{e as a,j as e}from"./vendor-DE_-CLIE.js";import{u as f}from"./useTeams-cnFAMG8m.js";import{Q as y,I as r}from"./main-yBKWfzqS.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function C(){y();const{createTeam:u}=f(),[o,p]=a.useState(""),[s,m]=a.useState(""),[n,b]=a.useState(""),[l,c]=a.useState(null),[d,x]=a.useState(!1),h=t=>{p(t),s||m(t.toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/-+/g,"-"))},g=async t=>{t.preventDefault(),c(null),x(!0);try{const i=await u({name:o,slug:s,description:n||void 0});window.location.href=`/teams/${i.id}`}catch(i){c(i instanceof Error?i.message:"Failed to create team")}finally{x(!1)}};return e.jsxs("div",{className:"mx-auto max-w-lg px-4 py-8",children:[e.jsx("h1",{className:"text-xl font-semibold text-text-primary mb-6",children:r("team.create.title")}),e.jsxs("form",{onSubmit:g,className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("label",{htmlFor:"name",className:"block text-sm font-medium text-text-primary mb-1",children:r("team.create.name")}),e.jsx("input",{id:"name",type:"text",required:!0,value:o,onChange:t=>h(t.target.value),className:"w-full rounded border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary",placeholder:"Engineering"})]}),e.jsxs("div",{children:[e.jsx("label",{htmlFor:"slug",className:"block text-sm font-medium text-text-primary mb-1",children:r("team.create.slug")}),e.jsx("input",{id:"slug",type:"text",required:!0,value:s,onChange:t=>m(t.target.value),pattern:"^[a-z0-9-]{3,32}$",className:"w-full rounded border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary",placeholder:"engineering"}),e.jsx("p",{className:"mt-1 text-xs text-text-muted",children:r("team.create.slugHint")})]}),e.jsxs("div",{children:[e.jsx("label",{htmlFor:"description",className:"block text-sm font-medium text-text-primary mb-1",children:r("team.create.description")}),e.jsx("textarea",{id:"description",value:n,onChange:t=>b(t.target.value),className:"w-full rounded border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary",rows:3})]}),l&&e.jsx("p",{className:"text-sm text-destructive",children:l}),e.jsxs("div",{className:"flex gap-3",children:[e.jsx("button",{type:"button",onClick:()=>window.history.back(),className:"rounded border border-border px-4 py-2 text-sm text-text-primary hover:bg-surface-2",children:r("common.cancel")}),e.jsx("button",{type:"submit",disabled:d||!o||!s,className:"rounded bg-accent px-4 py-2 text-sm text-white hover:bg-accent/90 disabled:opacity-50",children:d?r("common.creating"):r("team.create.submit")})]})]})]})}export{C as TeamCreate};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{e as i,j as e}from"./vendor-DE_-CLIE.js";import{x as f,k as b,Q as y,I as p,X as v,N as w}from"./main-
|
|
1
|
+
import{e as i,j as e}from"./vendor-DE_-CLIE.js";import{x as f,k as b,Q as y,I as p,X as v,N as w}from"./main-yBKWfzqS.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";/**
|
|
2
2
|
* @license lucide-react v0.555.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
package/packages/remote-control-server/web/dist/assets/{TeamList-C-Hte4nV.js → TeamList-BgDk6TT_.js}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as e}from"./vendor-DE_-CLIE.js";import{u as a}from"./useTeams-
|
|
1
|
+
import{j as e}from"./vendor-DE_-CLIE.js";import{u as a}from"./useTeams-cnFAMG8m.js";import{P as i}from"./main-yBKWfzqS.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function l(){const{myTeams:t,isLoading:r}=a();return r?e.jsx("div",{className:"flex items-center justify-center py-12 text-text-muted",children:"Loading teams..."}):e.jsxs("div",{className:"mx-auto max-w-3xl px-4 py-8",children:[e.jsxs("div",{className:"flex items-center justify-between mb-6",children:[e.jsx("h1",{className:"text-xl font-semibold text-text-primary",children:"Teams"}),e.jsxs("a",{href:"/teams/new",className:"inline-flex items-center gap-1.5 rounded bg-accent px-3 py-1.5 text-sm text-white hover:bg-accent/90",children:[e.jsx(i,{className:"h-4 w-4"}),"Create Team"]})]}),t.length===0?e.jsx("div",{className:"rounded border border-border/60 bg-surface-2 p-8 text-center",children:e.jsx("p",{className:"text-text-muted",children:"You are not a member of any teams yet."})}):e.jsx("ul",{className:"space-y-3",children:t.map(s=>e.jsx("li",{children:e.jsx("a",{href:`/teams/${s.id}`,className:"block rounded border border-border/60 bg-surface-2 p-4 hover:bg-surface-3 transition-colors",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"font-medium text-text-primary",children:s.name}),e.jsxs("p",{className:"text-sm text-text-muted",children:["/",s.slug]})]}),s.description&&e.jsx("p",{className:"text-sm text-text-muted max-w-xs truncate",children:s.description})]})})},s.id))})]})}export{l as TeamList};
|