toga-ai 1.0.48 → 1.0.49
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.
|
@@ -36,11 +36,12 @@ Dispatched via action `Elite/Webhook` on the worker queue.
|
|
|
36
36
|
|
|
37
37
|
## Constants
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
Defined in `worker2/Worker/Elite.php` — **values not reproduced here (credentials);
|
|
40
|
+
read them from the source/config:**
|
|
41
|
+
|
|
42
|
+
- `CLIENT_UUID_ELITE` — Elite's TOGA 2 client UUID
|
|
43
|
+
- `API_UUID_ELITE` — API identity UUID
|
|
44
|
+
- `API_SECRET_ELITE` — API secret (sensitive)
|
|
44
45
|
|
|
45
46
|
## Freshservice API — gotchas
|
|
46
47
|
|
|
@@ -3,10 +3,10 @@ title: Elite
|
|
|
3
3
|
framework: "2.0"
|
|
4
4
|
project: Worker
|
|
5
5
|
client: elite
|
|
6
|
-
type:
|
|
6
|
+
type: profile
|
|
7
7
|
status: active
|
|
8
8
|
updated: 2026-06-10
|
|
9
|
-
owners: []
|
|
9
|
+
owners: [snaredla]
|
|
10
10
|
files:
|
|
11
11
|
- worker2/Worker/Elite.php
|
|
12
12
|
- library/app/api/toga2.php
|
|
@@ -23,13 +23,12 @@ keeps Freshservice and TOGA 2 in sync via webhook-driven worker jobs.
|
|
|
23
23
|
|
|
24
24
|
## TOGA 2 API credentials
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
Three constants live in `worker2/Worker/Elite.php` — **values intentionally not reproduced
|
|
27
|
+
here. Read them from the source/config; never paste secret values into knowledge docs.**
|
|
27
28
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const API_SECRET_ELITE = 'c2701d21-1908-4895-aaed-2e6456710e8d';
|
|
32
|
-
```
|
|
29
|
+
- `CLIENT_UUID_ELITE` — Elite's TOGA 2 client UUID
|
|
30
|
+
- `API_UUID_ELITE` — API identity UUID
|
|
31
|
+
- `API_SECRET_ELITE` — API secret (sensitive; treat as a credential)
|
|
33
32
|
|
|
34
33
|
The library version of the sync methods (`library/app/api/toga2.php`) passes these in as
|
|
35
34
|
parameters — they are not constants there.
|
package/knowledge.js
CHANGED
|
@@ -541,6 +541,37 @@ function relRow(d, baseDir) {
|
|
|
541
541
|
return `| [${d.data.title || path.basename(d.file, '.md')}](${relLink(d, baseDir)}) | ${firstSentence(d.body)} | ${(d.data.files || []).join(', ')} |`;
|
|
542
542
|
}
|
|
543
543
|
|
|
544
|
+
/* ------------------------------------------------------------------ */
|
|
545
|
+
/* secret scanner — knowledge docs must never contain credential */
|
|
546
|
+
/* values. High-confidence patterns only (named secret assignments, */
|
|
547
|
+
/* AWS keys, PEM blocks) so legitimate UUIDs/IDs don't false-positive. */
|
|
548
|
+
/* Wired into validate → blocks publish on a hit. */
|
|
549
|
+
/* ------------------------------------------------------------------ */
|
|
550
|
+
|
|
551
|
+
const SECRET_NAME = /(secret|password|passwd|api[_-]?key|apikey|access[_-]?key|client[_-]?secret|private[_-]?key|auth[_-]?token|bearer)/i;
|
|
552
|
+
const SECRET_PLACEHOLDER = /(<[^>]+>|redact|example|placeholder|your[_-]|xxxx|\.\.\.|\*\*\*|changeme|dummy|sensitive|not reproduced)/i;
|
|
553
|
+
|
|
554
|
+
function scanSecrets(content) {
|
|
555
|
+
const hits = [];
|
|
556
|
+
const lines = content.split(/\r?\n/);
|
|
557
|
+
for (let i = 0; i < lines.length; i++) {
|
|
558
|
+
const ln = lines[i];
|
|
559
|
+
if (/-----BEGIN [A-Z0-9 ]*PRIVATE KEY-----/.test(ln)) { hits.push({ line: i + 1, reason: 'private key block' }); continue; }
|
|
560
|
+
if (/\bAKIA[0-9A-Z]{16}\b/.test(ln)) { hits.push({ line: i + 1, reason: 'AWS access key id' }); continue; }
|
|
561
|
+
// NAME = "value" or NAME: value where NAME looks like a credential
|
|
562
|
+
const m = ln.match(/([A-Za-z0-9_]*(?:secret|password|passwd|api[_-]?key|apikey|access[_-]?key|client[_-]?secret|private[_-]?key|auth[_-]?token)[A-Za-z0-9_]*)\s*[:=]\s*['"]?([^'"\s]{8,})['"]?/i);
|
|
563
|
+
if (m && SECRET_NAME.test(m[1]) && !SECRET_PLACEHOLDER.test(ln)) {
|
|
564
|
+
// Only flag a literal-looking value (hex/token/base64). Reject code
|
|
565
|
+
// references like `_Config::database(...)`, `getenv(...)`, `$var` — those
|
|
566
|
+
// are how secrets SHOULD be loaded, not leaked values.
|
|
567
|
+
const val = m[2];
|
|
568
|
+
const looksLiteral = /^[A-Za-z0-9_\-\/+=.]{8,}$/.test(val) && !/^[A-Z][A-Za-z0-9_]*$/.test(val);
|
|
569
|
+
if (looksLiteral) hits.push({ line: i + 1, reason: `literal value assigned to "${m[1]}"` });
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
return hits;
|
|
573
|
+
}
|
|
574
|
+
|
|
544
575
|
/* ------------------------------------------------------------------ */
|
|
545
576
|
/* command: validate */
|
|
546
577
|
/* ------------------------------------------------------------------ */
|
|
@@ -597,6 +628,10 @@ function cmdValidate() {
|
|
|
597
628
|
}
|
|
598
629
|
}
|
|
599
630
|
if (ELEVATED_TYPES.includes(d.data.type)) elevated.push(d.rel);
|
|
631
|
+
for (const s of scanSecrets(fs.readFileSync(d.file, 'utf8'))) {
|
|
632
|
+
fail(`${d.rel}:${s.line}: possible secret committed — ${s.reason}; redact it (reference the config/constant location, never paste credential values into knowledge docs)`);
|
|
633
|
+
ok = false;
|
|
634
|
+
}
|
|
600
635
|
}
|
|
601
636
|
|
|
602
637
|
if (elevated.length) {
|
package/package.json
CHANGED
package/skills/capture/SKILL.md
CHANGED
|
@@ -143,6 +143,12 @@ For a client `profile.md`, the `title:` **is** the client's formal name (e.g. "C
|
|
|
143
143
|
there is no separate name field; `validate` requires `title`. See New-client onboarding.
|
|
144
144
|
Add `related:` cross-links. Append new repos to `<TEAM_REPO>/knowledge/registry.json`.
|
|
145
145
|
|
|
146
|
+
**Never paste secret VALUES into a doc** — no API secrets, passwords, private keys, tokens,
|
|
147
|
+
or live credential strings. Document *where* a credential lives (the constant name, the
|
|
148
|
+
config key, the file) but not its value. `validate` (run by Step 6's publish and the
|
|
149
|
+
pre-commit hook) scans for credential literals and **fails the publish** if it finds one, so
|
|
150
|
+
a leaked secret blocks the whole capture until redacted. Reference, never reproduce.
|
|
151
|
+
|
|
146
152
|
## Step 6 — Publish (validate → index → mirror → rebase-push, one command)
|
|
147
153
|
|
|
148
154
|
Finish every capture with the deterministic publisher — **do not** run validate/index/git
|