@bigstrider/transcodes-cli 0.4.1 → 0.5.0
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/index.js +488 -83
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6028,6 +6028,17 @@ function dashboardHtml() {
|
|
|
6028
6028
|
object-fit: contain;
|
|
6029
6029
|
background: #f4f4f6;
|
|
6030
6030
|
padding: 8px;
|
|
6031
|
+
display: block;
|
|
6032
|
+
}
|
|
6033
|
+
.header-logo-link {
|
|
6034
|
+
flex-shrink: 0;
|
|
6035
|
+
border-radius: 14px;
|
|
6036
|
+
line-height: 0;
|
|
6037
|
+
transition: opacity 0.15s ease, box-shadow 0.15s ease;
|
|
6038
|
+
}
|
|
6039
|
+
.header-logo-link:hover {
|
|
6040
|
+
opacity: 0.88;
|
|
6041
|
+
box-shadow: 0 0 0 3px var(--accent-soft);
|
|
6031
6042
|
}
|
|
6032
6043
|
.header h1 {
|
|
6033
6044
|
margin: 0;
|
|
@@ -6035,11 +6046,41 @@ function dashboardHtml() {
|
|
|
6035
6046
|
font-weight: 700;
|
|
6036
6047
|
letter-spacing: -0.02em;
|
|
6037
6048
|
}
|
|
6038
|
-
.header
|
|
6039
|
-
|
|
6049
|
+
.header-title-link {
|
|
6050
|
+
color: inherit;
|
|
6051
|
+
text-decoration: none;
|
|
6052
|
+
transition: color 0.15s ease;
|
|
6053
|
+
}
|
|
6054
|
+
.header-title-link:hover {
|
|
6055
|
+
color: var(--accent);
|
|
6056
|
+
}
|
|
6057
|
+
.header-title-row {
|
|
6058
|
+
display: flex;
|
|
6059
|
+
align-items: center;
|
|
6060
|
+
flex-wrap: wrap;
|
|
6061
|
+
gap: 8px 12px;
|
|
6062
|
+
}
|
|
6063
|
+
.header-tagline {
|
|
6064
|
+
margin: 6px 0 0;
|
|
6040
6065
|
font-size: var(--text-sm);
|
|
6041
6066
|
color: var(--muted);
|
|
6042
6067
|
}
|
|
6068
|
+
.header-status {
|
|
6069
|
+
display: inline-flex;
|
|
6070
|
+
align-items: center;
|
|
6071
|
+
gap: 8px;
|
|
6072
|
+
font-size: var(--text-2xs);
|
|
6073
|
+
font-weight: 600;
|
|
6074
|
+
color: var(--muted);
|
|
6075
|
+
}
|
|
6076
|
+
.status-dot {
|
|
6077
|
+
width: 8px;
|
|
6078
|
+
height: 8px;
|
|
6079
|
+
border-radius: 50%;
|
|
6080
|
+
background: #22c55e;
|
|
6081
|
+
flex-shrink: 0;
|
|
6082
|
+
box-shadow: 0 0 0 2px rgba(34, 197, 94, 0.22);
|
|
6083
|
+
}
|
|
6043
6084
|
.tabs {
|
|
6044
6085
|
display: flex;
|
|
6045
6086
|
gap: 4px;
|
|
@@ -6077,7 +6118,52 @@ function dashboardHtml() {
|
|
|
6077
6118
|
.section-sub {
|
|
6078
6119
|
font-size: var(--text-base);
|
|
6079
6120
|
color: var(--muted);
|
|
6080
|
-
margin: 0 0
|
|
6121
|
+
margin: 0 0 16px;
|
|
6122
|
+
}
|
|
6123
|
+
.cli-map-row {
|
|
6124
|
+
display: flex;
|
|
6125
|
+
align-items: center;
|
|
6126
|
+
flex-wrap: wrap;
|
|
6127
|
+
gap: 6px;
|
|
6128
|
+
margin: 0 0 16px;
|
|
6129
|
+
font-size: var(--text-2xs);
|
|
6130
|
+
font-weight: 400;
|
|
6131
|
+
color: var(--muted);
|
|
6132
|
+
}
|
|
6133
|
+
.cli-map-row .cli-map-label {
|
|
6134
|
+
font-size: var(--text-sm);
|
|
6135
|
+
font-weight: 600;
|
|
6136
|
+
letter-spacing: 0.01em;
|
|
6137
|
+
}
|
|
6138
|
+
.cli-map-row .cli-map-label--title {
|
|
6139
|
+
font-size: var(--text-lg);
|
|
6140
|
+
font-weight: 700;
|
|
6141
|
+
color: var(--ink);
|
|
6142
|
+
letter-spacing: -0.01em;
|
|
6143
|
+
}
|
|
6144
|
+
.cli-map-row .cli-map-label--danger {
|
|
6145
|
+
font-size: var(--text-sm);
|
|
6146
|
+
font-weight: 700;
|
|
6147
|
+
color: #c0392f;
|
|
6148
|
+
}
|
|
6149
|
+
.cli-map-row .cli-map-label--ink { color: var(--ink); }
|
|
6150
|
+
.cli-map-row code {
|
|
6151
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
|
6152
|
+
background: var(--accent-soft);
|
|
6153
|
+
color: var(--accent);
|
|
6154
|
+
padding: 2px 8px;
|
|
6155
|
+
border-radius: 6px;
|
|
6156
|
+
font-size: var(--text-2xs);
|
|
6157
|
+
font-weight: 600;
|
|
6158
|
+
}
|
|
6159
|
+
.cli-map-row--list {
|
|
6160
|
+
margin: 26px 0 10px;
|
|
6161
|
+
}
|
|
6162
|
+
.cli-map-row--section {
|
|
6163
|
+
margin: 0 0 4px;
|
|
6164
|
+
}
|
|
6165
|
+
.cli-map-row--danger {
|
|
6166
|
+
margin: 0;
|
|
6081
6167
|
}
|
|
6082
6168
|
textarea {
|
|
6083
6169
|
width: 100%;
|
|
@@ -6142,6 +6228,67 @@ function dashboardHtml() {
|
|
|
6142
6228
|
color: #5a5a64;
|
|
6143
6229
|
}
|
|
6144
6230
|
.btn-secondary:hover:not(:disabled) { background: #ececf0; }
|
|
6231
|
+
.btn-inline-action {
|
|
6232
|
+
display: inline-flex;
|
|
6233
|
+
align-items: center;
|
|
6234
|
+
gap: 6px;
|
|
6235
|
+
padding: 7px 14px;
|
|
6236
|
+
font-size: var(--text-2xs);
|
|
6237
|
+
font-weight: 600;
|
|
6238
|
+
color: var(--accent);
|
|
6239
|
+
background: var(--accent-soft);
|
|
6240
|
+
border: none;
|
|
6241
|
+
border-radius: 9px;
|
|
6242
|
+
cursor: pointer;
|
|
6243
|
+
transition: background 0.15s ease;
|
|
6244
|
+
}
|
|
6245
|
+
.btn-inline-action:hover:not(:disabled) { background: #e3e1f7; }
|
|
6246
|
+
.btn-inline-action:disabled { opacity: 0.55; cursor: default; }
|
|
6247
|
+
.danger-zone {
|
|
6248
|
+
display: flex;
|
|
6249
|
+
align-items: center;
|
|
6250
|
+
justify-content: space-between;
|
|
6251
|
+
gap: 16px;
|
|
6252
|
+
flex-wrap: wrap;
|
|
6253
|
+
margin-top: 28px;
|
|
6254
|
+
padding: 18px 20px;
|
|
6255
|
+
border: 1px solid #f0d9d6;
|
|
6256
|
+
border-radius: 16px;
|
|
6257
|
+
background: #fdf6f5;
|
|
6258
|
+
}
|
|
6259
|
+
.danger-zone-desc {
|
|
6260
|
+
margin: 4px 0 0;
|
|
6261
|
+
font-size: var(--text-2xs);
|
|
6262
|
+
color: #8a8a94;
|
|
6263
|
+
line-height: 1.5;
|
|
6264
|
+
}
|
|
6265
|
+
.btn-danger {
|
|
6266
|
+
padding: 11px 22px;
|
|
6267
|
+
font-size: var(--text-sm);
|
|
6268
|
+
font-weight: 700;
|
|
6269
|
+
color: #fff;
|
|
6270
|
+
background: #c0392f;
|
|
6271
|
+
border: none;
|
|
6272
|
+
border-radius: 11px;
|
|
6273
|
+
cursor: pointer;
|
|
6274
|
+
transition: background 0.15s ease;
|
|
6275
|
+
white-space: nowrap;
|
|
6276
|
+
}
|
|
6277
|
+
.btn-danger:hover:not(:disabled) { background: #a52f26; }
|
|
6278
|
+
.btn-danger:disabled { opacity: 0.55; cursor: default; }
|
|
6279
|
+
.policy-refresh-bar {
|
|
6280
|
+
display: flex;
|
|
6281
|
+
align-items: center;
|
|
6282
|
+
justify-content: space-between;
|
|
6283
|
+
gap: 12px;
|
|
6284
|
+
flex-wrap: wrap;
|
|
6285
|
+
margin-bottom: 18px;
|
|
6286
|
+
padding: 14px 16px;
|
|
6287
|
+
border: 1px solid var(--line);
|
|
6288
|
+
border-radius: 14px;
|
|
6289
|
+
background: #fbfbfc;
|
|
6290
|
+
}
|
|
6291
|
+
.policy-refresh-bar .cli-map-row { margin: 0; flex: 1; min-width: 0; }
|
|
6145
6292
|
.list-label {
|
|
6146
6293
|
margin: 26px 0 10px;
|
|
6147
6294
|
font-size: var(--text-sm);
|
|
@@ -6277,6 +6424,39 @@ function dashboardHtml() {
|
|
|
6277
6424
|
.perm-chip-1 { color: #166534; border-color: #86efac; background: #f0fdf4; }
|
|
6278
6425
|
.perm-chip-2 { color: #7c3aed; border-color: #d8b4fe; background: #faf5ff; }
|
|
6279
6426
|
.field-k-rbac { color: #8a3ffc; font-weight: 600; }
|
|
6427
|
+
.field-status {
|
|
6428
|
+
display: flex;
|
|
6429
|
+
align-items: center;
|
|
6430
|
+
flex-wrap: wrap;
|
|
6431
|
+
gap: 6px 10px;
|
|
6432
|
+
}
|
|
6433
|
+
.status-chip {
|
|
6434
|
+
display: inline-block;
|
|
6435
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
|
6436
|
+
font-size: var(--text-xs);
|
|
6437
|
+
font-weight: 600;
|
|
6438
|
+
padding: 1px 7px;
|
|
6439
|
+
border-radius: 6px;
|
|
6440
|
+
border: 1px solid;
|
|
6441
|
+
text-transform: lowercase;
|
|
6442
|
+
line-height: inherit;
|
|
6443
|
+
vertical-align: baseline;
|
|
6444
|
+
}
|
|
6445
|
+
.status-chip-active {
|
|
6446
|
+
color: #166534;
|
|
6447
|
+
border-color: #86efac;
|
|
6448
|
+
background: #f0fdf4;
|
|
6449
|
+
}
|
|
6450
|
+
.status-chip-inactive {
|
|
6451
|
+
color: #9f1239;
|
|
6452
|
+
border-color: #fda4af;
|
|
6453
|
+
background: #fff1f2;
|
|
6454
|
+
}
|
|
6455
|
+
.status-hint {
|
|
6456
|
+
font-size: var(--text-2xs);
|
|
6457
|
+
color: var(--muted);
|
|
6458
|
+
line-height: 1.45;
|
|
6459
|
+
}
|
|
6280
6460
|
.admin-tools-count {
|
|
6281
6461
|
font-size: var(--text-sm);
|
|
6282
6462
|
color: var(--muted);
|
|
@@ -6465,6 +6645,40 @@ function dashboardHtml() {
|
|
|
6465
6645
|
flex-direction: column;
|
|
6466
6646
|
gap: 10px;
|
|
6467
6647
|
}
|
|
6648
|
+
.guide-groups {
|
|
6649
|
+
display: flex;
|
|
6650
|
+
flex-direction: column;
|
|
6651
|
+
gap: 22px;
|
|
6652
|
+
}
|
|
6653
|
+
.guide-group-label {
|
|
6654
|
+
margin: 0 0 10px;
|
|
6655
|
+
font-size: var(--text-sm);
|
|
6656
|
+
font-weight: 700;
|
|
6657
|
+
color: var(--ink);
|
|
6658
|
+
letter-spacing: 0.01em;
|
|
6659
|
+
}
|
|
6660
|
+
a.guide-group-label {
|
|
6661
|
+
display: inline-flex;
|
|
6662
|
+
align-items: center;
|
|
6663
|
+
gap: 6px;
|
|
6664
|
+
text-decoration: none;
|
|
6665
|
+
color: var(--ink);
|
|
6666
|
+
}
|
|
6667
|
+
a.guide-group-label:hover {
|
|
6668
|
+
color: var(--accent);
|
|
6669
|
+
}
|
|
6670
|
+
a.guide-group-label:hover .guide-group-link-icon {
|
|
6671
|
+
color: var(--accent);
|
|
6672
|
+
}
|
|
6673
|
+
.guide-group-link-icon {
|
|
6674
|
+
display: inline-flex;
|
|
6675
|
+
align-items: center;
|
|
6676
|
+
color: var(--muted);
|
|
6677
|
+
line-height: 0;
|
|
6678
|
+
transition: color 0.15s ease;
|
|
6679
|
+
}
|
|
6680
|
+
.guide-group--panel .guide-group-label { color: var(--accent); }
|
|
6681
|
+
.guide-group--agent .guide-group-label { color: #5a5a64; }
|
|
6468
6682
|
.guide-step {
|
|
6469
6683
|
display: flex;
|
|
6470
6684
|
gap: 14px;
|
|
@@ -6508,6 +6722,15 @@ function dashboardHtml() {
|
|
|
6508
6722
|
padding: 1px 6px;
|
|
6509
6723
|
border-radius: 6px;
|
|
6510
6724
|
}
|
|
6725
|
+
.guide-step-desc-row {
|
|
6726
|
+
display: flex;
|
|
6727
|
+
align-items: center;
|
|
6728
|
+
flex-wrap: wrap;
|
|
6729
|
+
gap: 8px 12px;
|
|
6730
|
+
}
|
|
6731
|
+
.guide-step .toast {
|
|
6732
|
+
margin-top: 10px;
|
|
6733
|
+
}
|
|
6511
6734
|
.guide-help {
|
|
6512
6735
|
margin: 0 0 18px;
|
|
6513
6736
|
padding: 16px 18px;
|
|
@@ -6559,10 +6782,18 @@ function dashboardHtml() {
|
|
|
6559
6782
|
<body>
|
|
6560
6783
|
<div class="card">
|
|
6561
6784
|
<div class="header">
|
|
6562
|
-
<
|
|
6785
|
+
<a class="header-logo-link" href="https://app.transcodes.io/" target="_blank" rel="noopener noreferrer" aria-label="Open Transcodes console">
|
|
6786
|
+
<img class="avatar" src="${LOGO_DATA_URI}" alt="Transcodes" />
|
|
6787
|
+
</a>
|
|
6563
6788
|
<div>
|
|
6564
|
-
<
|
|
6565
|
-
|
|
6789
|
+
<div class="header-title-row">
|
|
6790
|
+
<h1><a class="header-title-link" href="https://app.transcodes.io/" target="_blank" rel="noopener noreferrer">Transcodes</a> CLI Panel</h1>
|
|
6791
|
+
<span class="header-status">
|
|
6792
|
+
<span class="status-dot" aria-hidden="true"></span>
|
|
6793
|
+
Connected
|
|
6794
|
+
</span>
|
|
6795
|
+
</div>
|
|
6796
|
+
<p class="header-tagline">Manage credentials and rules from one panel \u2014 no CLI typing required</p>
|
|
6566
6797
|
</div>
|
|
6567
6798
|
</div>
|
|
6568
6799
|
<div class="tabs">
|
|
@@ -6589,68 +6820,104 @@ function dashboardHtml() {
|
|
|
6589
6820
|
></mux-player>
|
|
6590
6821
|
</div>
|
|
6591
6822
|
<p class="list-label">Quick setup</p>
|
|
6592
|
-
<
|
|
6593
|
-
<
|
|
6594
|
-
<span class="guide-
|
|
6595
|
-
<
|
|
6596
|
-
<
|
|
6597
|
-
|
|
6598
|
-
|
|
6599
|
-
|
|
6600
|
-
|
|
6601
|
-
|
|
6602
|
-
|
|
6603
|
-
<
|
|
6604
|
-
|
|
6605
|
-
|
|
6606
|
-
|
|
6607
|
-
|
|
6608
|
-
|
|
6609
|
-
|
|
6610
|
-
<
|
|
6611
|
-
|
|
6612
|
-
|
|
6613
|
-
|
|
6614
|
-
|
|
6615
|
-
|
|
6616
|
-
|
|
6617
|
-
<
|
|
6618
|
-
|
|
6619
|
-
|
|
6620
|
-
|
|
6621
|
-
|
|
6622
|
-
|
|
6623
|
-
|
|
6624
|
-
|
|
6625
|
-
|
|
6626
|
-
|
|
6627
|
-
|
|
6628
|
-
|
|
6629
|
-
<
|
|
6630
|
-
|
|
6631
|
-
|
|
6632
|
-
|
|
6633
|
-
|
|
6634
|
-
|
|
6635
|
-
|
|
6636
|
-
|
|
6637
|
-
|
|
6638
|
-
|
|
6639
|
-
|
|
6640
|
-
|
|
6641
|
-
|
|
6642
|
-
|
|
6643
|
-
|
|
6644
|
-
|
|
6645
|
-
|
|
6646
|
-
|
|
6647
|
-
|
|
6648
|
-
|
|
6649
|
-
|
|
6823
|
+
<div class="guide-groups">
|
|
6824
|
+
<section class="guide-group guide-group--console">
|
|
6825
|
+
<a class="guide-group-label" href="https://app.transcodes.io/" target="_blank" rel="noopener noreferrer">Transcodes Console<span class="guide-group-link-icon" aria-hidden="true"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></span></a>
|
|
6826
|
+
<ol class="guide-steps">
|
|
6827
|
+
<li class="guide-step">
|
|
6828
|
+
<span class="guide-step-num">1</span>
|
|
6829
|
+
<div class="guide-step-body">
|
|
6830
|
+
<p class="guide-step-title">Create a project</p>
|
|
6831
|
+
<p class="guide-step-desc">Create a new project for your app</p>
|
|
6832
|
+
</div>
|
|
6833
|
+
</li>
|
|
6834
|
+
<li class="guide-step">
|
|
6835
|
+
<span class="guide-step-num">2</span>
|
|
6836
|
+
<div class="guide-step-body">
|
|
6837
|
+
<p class="guide-step-title">Create an authentication cluster</p>
|
|
6838
|
+
<p class="guide-step-desc">Add an authentication cluster to define how members sign in and authenticate</p>
|
|
6839
|
+
</div>
|
|
6840
|
+
</li>
|
|
6841
|
+
<li class="guide-step">
|
|
6842
|
+
<span class="guide-step-num">3</span>
|
|
6843
|
+
<div class="guide-step-body">
|
|
6844
|
+
<p class="guide-step-title">Add a member</p>
|
|
6845
|
+
<p class="guide-step-desc">Invite or add a member so they can be issued an access token</p>
|
|
6846
|
+
</div>
|
|
6847
|
+
</li>
|
|
6848
|
+
<li class="guide-step">
|
|
6849
|
+
<span class="guide-step-num">4</span>
|
|
6850
|
+
<div class="guide-step-body">
|
|
6851
|
+
<p class="guide-step-title">Issue an access token</p>
|
|
6852
|
+
<p class="guide-step-desc">Open the member detail page and issue a Member Access Token (MAT) for the agent</p>
|
|
6853
|
+
</div>
|
|
6854
|
+
</li>
|
|
6855
|
+
</ol>
|
|
6856
|
+
</section>
|
|
6857
|
+
|
|
6858
|
+
<section class="guide-group guide-group--panel">
|
|
6859
|
+
<p class="guide-group-label">This CLI panel</p>
|
|
6860
|
+
<ol class="guide-steps">
|
|
6861
|
+
<li class="guide-step">
|
|
6862
|
+
<span class="guide-step-num">5</span>
|
|
6863
|
+
<div class="guide-step-body">
|
|
6864
|
+
<p class="guide-step-title">Save the token</p>
|
|
6865
|
+
<p class="guide-step-desc">Paste the token in the Tokens tab with a label (e.g. <code>transcodes-myapp-dev</code>) \u2014 the plugin reads it from <code>{{HOME_DIR}}/.transcodes/config.json</code></p>
|
|
6866
|
+
</div>
|
|
6867
|
+
</li>
|
|
6868
|
+
</ol>
|
|
6869
|
+
</section>
|
|
6870
|
+
|
|
6871
|
+
<section class="guide-group guide-group--agent">
|
|
6872
|
+
<p class="guide-group-label">LLM agent (Claude, Cursor, Codex, Antigravity)</p>
|
|
6873
|
+
<ol class="guide-steps">
|
|
6874
|
+
<li class="guide-step">
|
|
6875
|
+
<span class="guide-step-num">6</span>
|
|
6876
|
+
<div class="guide-step-body">
|
|
6877
|
+
<p class="guide-step-title">Ask your local agent to add a custom rule</p>
|
|
6878
|
+
<p class="guide-step-desc">Use <code>add_tool_rule</code> or <code>add_user_pattern</code> \u2014 on first registration, rules are <code>inactive</code> and not applied to MCP</p>
|
|
6879
|
+
</div>
|
|
6880
|
+
</li>
|
|
6881
|
+
</ol>
|
|
6882
|
+
</section>
|
|
6883
|
+
|
|
6884
|
+
<section class="guide-group guide-group--console">
|
|
6885
|
+
<a class="guide-group-label" href="https://app.transcodes.io/" target="_blank" rel="noopener noreferrer">Transcodes Console<span class="guide-group-link-icon" aria-hidden="true"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></span></a>
|
|
6886
|
+
<ol class="guide-steps">
|
|
6887
|
+
<li class="guide-step">
|
|
6888
|
+
<span class="guide-step-num">7</span>
|
|
6889
|
+
<div class="guide-step-body">
|
|
6890
|
+
<p class="guide-step-title">Approve the rule</p>
|
|
6891
|
+
<p class="guide-step-desc">Switch the rule to <code>active</code> \u2014 only then is it enforced on MCP</p>
|
|
6892
|
+
</div>
|
|
6893
|
+
</li>
|
|
6894
|
+
</ol>
|
|
6895
|
+
</section>
|
|
6896
|
+
|
|
6897
|
+
<section class="guide-group guide-group--panel">
|
|
6898
|
+
<p class="guide-group-label">This CLI panel</p>
|
|
6899
|
+
<ol class="guide-steps">
|
|
6900
|
+
<li class="guide-step">
|
|
6901
|
+
<span class="guide-step-num">8</span>
|
|
6902
|
+
<div class="guide-step-body">
|
|
6903
|
+
<p class="guide-step-title">Refresh active rules locally</p>
|
|
6904
|
+
<p class="guide-step-desc guide-step-desc-row">
|
|
6905
|
+
Run terminal <code>transcodes policy refresh</code> or
|
|
6906
|
+
<button type="button" class="btn-inline-action" id="guide-policy-refresh">Refresh</button>
|
|
6907
|
+
</p>
|
|
6908
|
+
<div id="guide-toast" class="toast"></div>
|
|
6909
|
+
</div>
|
|
6910
|
+
</li>
|
|
6911
|
+
</ol>
|
|
6912
|
+
</section>
|
|
6913
|
+
</div>
|
|
6650
6914
|
</div>
|
|
6651
6915
|
|
|
6652
6916
|
<div class="panel" id="panel-tokens">
|
|
6653
|
-
<p class="section
|
|
6917
|
+
<p class="cli-map-row cli-map-row--section">
|
|
6918
|
+
<span class="cli-map-label cli-map-label--title">MCP Access Token</span>
|
|
6919
|
+
<code>transcodes set <token> -l <label></code>
|
|
6920
|
+
</p>
|
|
6654
6921
|
<p class="section-sub">Paste the token from your Transcodes console member detail page</p>
|
|
6655
6922
|
<textarea id="token" placeholder="eyJhbGciOi\u2026" spellcheck="false" autocomplete="off"></textarea>
|
|
6656
6923
|
<input type="text" id="label" class="label-input" placeholder="Label (required) \u2014 e.g. transcodes-{project_name}-{env}" autocomplete="off" required />
|
|
@@ -6659,8 +6926,21 @@ function dashboardHtml() {
|
|
|
6659
6926
|
<button type="button" class="btn-secondary" id="clear">Clear</button>
|
|
6660
6927
|
</div>
|
|
6661
6928
|
<div id="toast" class="toast"></div>
|
|
6662
|
-
<p class="list
|
|
6929
|
+
<p class="cli-map-row cli-map-row--list">
|
|
6930
|
+
<span class="cli-map-label">Saved tokens</span>
|
|
6931
|
+
<code>transcodes tokens</code>
|
|
6932
|
+
</p>
|
|
6663
6933
|
<div class="token-list" id="token-list"></div>
|
|
6934
|
+
<div class="danger-zone">
|
|
6935
|
+
<div class="danger-zone-text">
|
|
6936
|
+
<p class="cli-map-row cli-map-row--danger">
|
|
6937
|
+
<span class="cli-map-label cli-map-label--danger">Reset all tokens</span>
|
|
6938
|
+
<code>transcodes reset</code>
|
|
6939
|
+
</p>
|
|
6940
|
+
<p class="danger-zone-desc">Remove every saved token from this machine</p>
|
|
6941
|
+
</div>
|
|
6942
|
+
<button type="button" class="btn-danger" id="reset-all">Reset all</button>
|
|
6943
|
+
</div>
|
|
6664
6944
|
<p class="hint">Saved to <code>{{HOME_DIR}}/.transcodes/config.json</code><br />Press Ctrl+C in the terminal to stop</p>
|
|
6665
6945
|
</div>
|
|
6666
6946
|
|
|
@@ -6675,11 +6955,11 @@ function dashboardHtml() {
|
|
|
6675
6955
|
<div class="panel" id="panel-rules">
|
|
6676
6956
|
<p id="policy-token-warning" class="policy-token-warning" hidden>transcodes\uB97C \uB85C\uCEEC \uC5D0\uC774\uC804\uD2B8\uC5D0\uC11C \uC774\uC6A9\uD558\uAE30 \uC704\uD574\uC120 \uD1A0\uD070\uC774 \uD558\uB098 \uC774\uC0C1 \uB4F1\uB85D\uC774 \uB418\uC5B4\uC57C \uD569\uB2C8\uB2E4</p>
|
|
6677
6957
|
<div class="tabs sub-tabs" role="tablist" aria-label="Rule type">
|
|
6678
|
-
<button type="button" class="tab active" data-policy="project" role="tab">Project
|
|
6679
|
-
<button type="button" class="tab" data-policy="admin" role="tab">
|
|
6958
|
+
<button type="button" class="tab active" data-policy="project" role="tab">Project</button>
|
|
6959
|
+
<button type="button" class="tab" data-policy="admin" role="tab">Transcodes</button>
|
|
6680
6960
|
</div>
|
|
6681
6961
|
<div class="policy-pane active" id="policy-pane-project">
|
|
6682
|
-
<p class="section-title">Step-up
|
|
6962
|
+
<p class="section-title">Custom Project Step-up Rules</p>
|
|
6683
6963
|
<p class="section-sub">When an active rule matches an agent action, Transcodes step-up authentication is triggered. Rules are registered only from your local agent; activating and deleting them is done in the Transcodes web console</p>
|
|
6684
6964
|
<div class="usage">
|
|
6685
6965
|
<p class="usage-title">How rules work</p>
|
|
@@ -6695,15 +6975,22 @@ function dashboardHtml() {
|
|
|
6695
6975
|
<span class="q">\u2192 the agent registers it as <code>inactive</code>; activate it in the Transcodes web console to start enforcing</span>
|
|
6696
6976
|
</div>
|
|
6697
6977
|
</div>
|
|
6978
|
+
<div class="policy-refresh-bar">
|
|
6979
|
+
<p class="cli-map-row">
|
|
6980
|
+
<span class="cli-map-label cli-map-label--ink">Refresh Custom Project Rules</span>
|
|
6981
|
+
<code>transcodes policy refresh</code>
|
|
6982
|
+
</p>
|
|
6983
|
+
<button type="button" class="btn-inline-action" id="policy-refresh">Refresh</button>
|
|
6984
|
+
</div>
|
|
6698
6985
|
<div id="rules-toast" class="toast"></div>
|
|
6699
|
-
<p class="list-label">Your
|
|
6986
|
+
<p class="list-label">Your Project MCP Rules</p>
|
|
6700
6987
|
<div class="token-list" id="project-rules-list"></div>
|
|
6701
6988
|
<p class="list-label">System bash patterns (read-only)</p>
|
|
6702
6989
|
<div class="token-list" id="system-patterns-list"></div>
|
|
6703
6990
|
</div>
|
|
6704
6991
|
|
|
6705
6992
|
<div class="policy-pane" id="policy-pane-admin">
|
|
6706
|
-
<p class="section-title">Transcodes
|
|
6993
|
+
<p class="section-title">Transcodes MCP Rules</p>
|
|
6707
6994
|
<p class="section-sub">Backend API tools exposed via MCP \u2014 agents call these through the transcodes-guard plugin. Read-only reference for system tool-rules.</p>
|
|
6708
6995
|
<div class="rbac-legend">
|
|
6709
6996
|
<p class="rbac-legend-title">Role permission check</p>
|
|
@@ -6942,6 +7229,28 @@ function dashboardHtml() {
|
|
|
6942
7229
|
tokenEl.focus();
|
|
6943
7230
|
});
|
|
6944
7231
|
|
|
7232
|
+
const resetAllBtn = document.getElementById("reset-all");
|
|
7233
|
+
resetAllBtn.addEventListener("click", async () => {
|
|
7234
|
+
const count = (lastStatus.tokens || []).length;
|
|
7235
|
+
if (count === 0) {
|
|
7236
|
+
showToast("No tokens to reset", "error");
|
|
7237
|
+
return;
|
|
7238
|
+
}
|
|
7239
|
+
if (!confirm("Remove ALL " + count + " saved token(s)? This cannot be undone.")) return;
|
|
7240
|
+
resetAllBtn.disabled = true;
|
|
7241
|
+
try {
|
|
7242
|
+
const res = await fetch("/api/tokens", { method: "DELETE" });
|
|
7243
|
+
const data = await res.json();
|
|
7244
|
+
if (!res.ok) throw new Error(data.error || "Reset failed");
|
|
7245
|
+
showToast("All tokens removed", "success");
|
|
7246
|
+
refresh();
|
|
7247
|
+
} catch (e) {
|
|
7248
|
+
showToast(e.message || "Reset failed", "error");
|
|
7249
|
+
} finally {
|
|
7250
|
+
resetAllBtn.disabled = false;
|
|
7251
|
+
}
|
|
7252
|
+
});
|
|
7253
|
+
|
|
6945
7254
|
const rulesToastEl = document.getElementById("rules-toast");
|
|
6946
7255
|
const projectRulesListEl = document.getElementById("project-rules-list");
|
|
6947
7256
|
const systemPatternsListEl = document.getElementById("system-patterns-list");
|
|
@@ -6971,6 +7280,41 @@ function dashboardHtml() {
|
|
|
6971
7280
|
);
|
|
6972
7281
|
}
|
|
6973
7282
|
|
|
7283
|
+
function ruleStatusField(status) {
|
|
7284
|
+
if (!status) return "";
|
|
7285
|
+
const chipClass =
|
|
7286
|
+
status === "active"
|
|
7287
|
+
? "status-chip-active"
|
|
7288
|
+
: status === "inactive"
|
|
7289
|
+
? "status-chip-inactive"
|
|
7290
|
+
: "";
|
|
7291
|
+
const chip = chipClass
|
|
7292
|
+
? '<span class="status-chip ' + chipClass + '">' + esc(status) + "</span>"
|
|
7293
|
+
: "<code>" + esc(status) + "</code>";
|
|
7294
|
+
const hint =
|
|
7295
|
+
status === "inactive"
|
|
7296
|
+
? '<span class="status-hint">Activate in the console to take effect on MCP</span>'
|
|
7297
|
+
: "";
|
|
7298
|
+
return (
|
|
7299
|
+
'<div class="field field-status">' +
|
|
7300
|
+
'<span class="k">status</span> ' +
|
|
7301
|
+
chip +
|
|
7302
|
+
hint +
|
|
7303
|
+
"</div>"
|
|
7304
|
+
);
|
|
7305
|
+
}
|
|
7306
|
+
|
|
7307
|
+
function ruleResourceActionField(r) {
|
|
7308
|
+
const resource = r.resource || "\u2014";
|
|
7309
|
+
const action = r.action || "\u2014";
|
|
7310
|
+
return (
|
|
7311
|
+
'<div class="field">' +
|
|
7312
|
+
'<span class="k">resource / action</span> ' +
|
|
7313
|
+
"<code>" + esc(resource) + "</code> / <code>" + esc(action) + "</code>" +
|
|
7314
|
+
"</div>"
|
|
7315
|
+
);
|
|
7316
|
+
}
|
|
7317
|
+
|
|
6974
7318
|
function projectRuleRow(r) {
|
|
6975
7319
|
const editing = r.id === ruleEditingId;
|
|
6976
7320
|
const idField = '<div class="field"><span class="k">id</span> <code>' + esc(r.id) + '</code></div>';
|
|
@@ -7002,19 +7346,14 @@ function dashboardHtml() {
|
|
|
7002
7346
|
const description = r.description
|
|
7003
7347
|
? '<div class="label">' + esc(r.description) + '</div>'
|
|
7004
7348
|
: '';
|
|
7349
|
+
const status = ruleStatusField(r.status);
|
|
7350
|
+
const resourceAction = ruleResourceActionField(r);
|
|
7005
7351
|
const matcher =
|
|
7006
7352
|
'<div class="field"><span class="k">matcher</span> <code>' + esc(r.matcher || (r.type === 'bash' ? 'regex' : 'exact')) + '</code></div>';
|
|
7007
|
-
const action =
|
|
7008
|
-
'<div class="field"><span class="k">action</span> <code>' + esc(r.action || '\u2014') + '</code></div>';
|
|
7009
|
-
const resource =
|
|
7010
|
-
'<div class="field"><span class="k">resource</span> <code>' + esc(r.resource || '\u2014') + '</code></div>';
|
|
7011
|
-
const status = r.status
|
|
7012
|
-
? '<div class="field"><span class="k">status</span> <code>' + esc(r.status) + '</code></div>'
|
|
7013
|
-
: '';
|
|
7014
7353
|
return (
|
|
7015
7354
|
'<div class="token-row">' +
|
|
7016
7355
|
'<div class="token-top">' +
|
|
7017
|
-
'<div class="token-info">' + description +
|
|
7356
|
+
'<div class="token-info">' + description + status + resourceAction + typeField + idField + labelField + matcher + '</div>' +
|
|
7018
7357
|
'</div>' +
|
|
7019
7358
|
'<div class="token-actions">' +
|
|
7020
7359
|
'<button type="button" class="btn-edit" data-edit-rule="' + esc(r.id) + '">EDIT</button>' +
|
|
@@ -7049,6 +7388,42 @@ function dashboardHtml() {
|
|
|
7049
7388
|
renderProjectRules(await res.json());
|
|
7050
7389
|
}
|
|
7051
7390
|
|
|
7391
|
+
const guideToastEl = document.getElementById("guide-toast");
|
|
7392
|
+
function showGuideToast(msg, kind) {
|
|
7393
|
+
guideToastEl.textContent = msg;
|
|
7394
|
+
guideToastEl.className = "toast show " + (kind || "success");
|
|
7395
|
+
setTimeout(() => guideToastEl.classList.remove("show"), 4000);
|
|
7396
|
+
}
|
|
7397
|
+
|
|
7398
|
+
async function runPolicyRefresh(btn, showToastFn) {
|
|
7399
|
+
btn.disabled = true;
|
|
7400
|
+
const original = btn.textContent;
|
|
7401
|
+
btn.textContent = "Refreshing\u2026";
|
|
7402
|
+
try {
|
|
7403
|
+
const res = await fetch("/api/policy/refresh", { method: "POST" });
|
|
7404
|
+
const data = await res.json();
|
|
7405
|
+
if (!res.ok) throw new Error(data.error || "Refresh failed");
|
|
7406
|
+
const detail = data.revision != null
|
|
7407
|
+
? " (revision " + data.revision + ", " + data.rules + " rules)"
|
|
7408
|
+
: "";
|
|
7409
|
+
showToastFn(
|
|
7410
|
+
(data.outcome === "not-modified" ? "Policy already current" : "Policy bundle refreshed") + detail,
|
|
7411
|
+
"success");
|
|
7412
|
+
loadProjectRules();
|
|
7413
|
+
} catch (e) {
|
|
7414
|
+
showToastFn(e.message || "Refresh failed", "error");
|
|
7415
|
+
} finally {
|
|
7416
|
+
btn.disabled = false;
|
|
7417
|
+
btn.textContent = original;
|
|
7418
|
+
}
|
|
7419
|
+
}
|
|
7420
|
+
|
|
7421
|
+
const policyRefreshBtn = document.getElementById("policy-refresh");
|
|
7422
|
+
policyRefreshBtn.addEventListener("click", () => runPolicyRefresh(policyRefreshBtn, showRulesToast));
|
|
7423
|
+
document.getElementById("guide-policy-refresh").addEventListener(
|
|
7424
|
+
"click",
|
|
7425
|
+
() => runPolicyRefresh(document.getElementById("guide-policy-refresh"), showGuideToast));
|
|
7426
|
+
|
|
7052
7427
|
function findEditingRule(id) {
|
|
7053
7428
|
return (lastProjectRules.project || []).find((r) => r.id === id);
|
|
7054
7429
|
}
|
|
@@ -7102,10 +7477,9 @@ function dashboardHtml() {
|
|
|
7102
7477
|
? '<div class="tool-badges"><span class="tool-badge rbac-gated" title="Outcome follows your role matrix: 0 block, 1 allow, 2 step-up MFA">Role permission check</span></div>'
|
|
7103
7478
|
: '';
|
|
7104
7479
|
const rbacFields = t.rbacGated
|
|
7105
|
-
? '<div class="field"><span class="k field-k-rbac">
|
|
7106
|
-
esc(t.
|
|
7107
|
-
|
|
7108
|
-
esc(t.rbacResource || 'system') + '</code></div>'
|
|
7480
|
+
? '<div class="field"><span class="k field-k-rbac">Resource / Action</span> : ' +
|
|
7481
|
+
'<code>' + esc(t.rbacResource || 'system') + '</code> / <code>' +
|
|
7482
|
+
esc(t.rbacAction || 'update') + '</code></div>'
|
|
7109
7483
|
: '';
|
|
7110
7484
|
return (
|
|
7111
7485
|
'<div class="token-row">' +
|
|
@@ -7240,6 +7614,37 @@ function listen(port) {
|
|
|
7240
7614
|
sendJson(res, 200, { ok: true, ...buildStatus() });
|
|
7241
7615
|
return;
|
|
7242
7616
|
}
|
|
7617
|
+
if (method === "DELETE" && url === "/api/tokens") {
|
|
7618
|
+
clearTokenFile();
|
|
7619
|
+
sendJson(res, 200, { ok: true, ...buildStatus() });
|
|
7620
|
+
return;
|
|
7621
|
+
}
|
|
7622
|
+
if (method === "POST" && url === "/api/policy/refresh") {
|
|
7623
|
+
let config;
|
|
7624
|
+
try {
|
|
7625
|
+
config = loadStepupConfig();
|
|
7626
|
+
} catch (err) {
|
|
7627
|
+
sendJson(res, 400, {
|
|
7628
|
+
error: err instanceof Error ? err.message : String(err)
|
|
7629
|
+
});
|
|
7630
|
+
return;
|
|
7631
|
+
}
|
|
7632
|
+
const outcome = await refreshPolicyBundle(config, { force: true });
|
|
7633
|
+
if (outcome === "failed") {
|
|
7634
|
+
sendJson(res, 502, {
|
|
7635
|
+
error: "policy bundle refresh failed \u2014 previous cache (if any) kept"
|
|
7636
|
+
});
|
|
7637
|
+
return;
|
|
7638
|
+
}
|
|
7639
|
+
const cached = readCachedPolicyBundle(config.projectId);
|
|
7640
|
+
sendJson(res, 200, {
|
|
7641
|
+
ok: true,
|
|
7642
|
+
outcome,
|
|
7643
|
+
revision: cached?.bundle.revision,
|
|
7644
|
+
rules: cached?.bundle.rules.length
|
|
7645
|
+
});
|
|
7646
|
+
return;
|
|
7647
|
+
}
|
|
7243
7648
|
if (method === "GET" && url === "/api/project-rules") {
|
|
7244
7649
|
sendJson(res, 200, await fetchProjectRulesFromBackend());
|
|
7245
7650
|
return;
|
package/package.json
CHANGED