feed-the-machine 1.7.4 → 1.7.6
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/ftm-audit/SKILL.md +2 -2
- package/ftm-capture/SKILL.md +5 -4
- package/ftm-mind/references/orient-protocol.md +40 -2
- package/ftm-state/blackboard/context.json +10 -23
- package/ftm-state/blackboard/experiences/index.json +3 -52
- package/package.json +1 -1
- package/ftm-state/blackboard/experiences/doom-statusline-fix.json +0 -26
- package/ftm-state/blackboard/experiences/hackathon-pages-site.json +0 -26
- package/ftm-state/blackboard/experiences/hindsight-sso-kickoff.json +0 -42
- package/ftm-state/blackboard/experiences/learning-ragnarok-api-access.json +0 -23
- package/ftm-state/blackboard/experiences/nordlayer-members-auto-assign.json +0 -26
- package/ftm-state/blackboard/experiences/saml2aws-stale-session-fix.json +0 -41
package/ftm-audit/SKILL.md
CHANGED
|
@@ -223,7 +223,7 @@ Append a row to the root INTENT.md module map table:
|
|
|
223
223
|
|---------|----------|---------------|
|
|
224
224
|
| `BROKEN_PATH` — path in .md file doesn't resolve from installed location | HARD FAIL | No — requires human decision on correct path |
|
|
225
225
|
| `BROKEN_CLI` — CLI command path doesn't exist or errors on execution | HARD FAIL | No — requires fixing the path or creating a symlink |
|
|
226
|
-
| `HARDCODED_USER_PATH` — absolute path contains a specific username (e.g., `/Users/
|
|
226
|
+
| `HARDCODED_USER_PATH` — absolute path contains a specific username (e.g., `/Users/jdoe/`) | WARN | Yes — replace with `~/` or `$HOME/` equivalent |
|
|
227
227
|
| `STALE_PATH_REFERENCE` — path references a directory/file that was moved or renamed in this diff | HARD FAIL | Yes — update to new path |
|
|
228
228
|
|
|
229
229
|
**Output format:**
|
|
@@ -231,7 +231,7 @@ Append a row to the root INTENT.md module map table:
|
|
|
231
231
|
Layer 1.75 findings:
|
|
232
232
|
- [BROKEN_PATH] ftm-ops/SKILL.md:53 — `~/.claude/skills/ftm/bin/brain.py` does not exist (ftm/ points to router subdirectory, not repo root)
|
|
233
233
|
- [BROKEN_CLI] ftm-mind/references/orient-protocol.md:210 — `python3 ~/.claude/skills/eng-buddy/bin/brain.py` → file not found
|
|
234
|
-
- [HARDCODED_USER_PATH] ftm-mind/references/ops-routing.md:44 — `/Users/
|
|
234
|
+
- [HARDCODED_USER_PATH] ftm-mind/references/ops-routing.md:44 — `/Users/jdoe/.claude/eng-buddy/drafts/` contains hardcoded username
|
|
235
235
|
- [STALE_PATH_REFERENCE] ftm-ops/references/task-management.md:15 — `~/.claude/eng-buddy/active-tasks.md` was moved to `~/.claude/ftm-ops/active-tasks.md`
|
|
236
236
|
```
|
|
237
237
|
|
package/ftm-capture/SKILL.md
CHANGED
|
@@ -97,7 +97,7 @@ Ask the user focused questions to determine generalizability. DO NOT ask more th
|
|
|
97
97
|
- "Should I parameterize [specific value] or hardcode it?"
|
|
98
98
|
|
|
99
99
|
**Environment questions:**
|
|
100
|
-
- "Does this only work in the
|
|
100
|
+
- "Does this only work in the current repo, or should it be repo-agnostic?"
|
|
101
101
|
- "Are there API access requirements I should document?"
|
|
102
102
|
|
|
103
103
|
### Step 4: Write the Routine (`~/.ftm/routines/{name}.yml`)
|
|
@@ -306,9 +306,10 @@ ftm-ops's playbook engine reads from `~/.claude/ftm-ops/playbooks/`. Captured pl
|
|
|
306
306
|
### Environment Awareness
|
|
307
307
|
|
|
308
308
|
When capturing, always note the environment context:
|
|
309
|
-
- **
|
|
310
|
-
- **If
|
|
311
|
-
- **
|
|
309
|
+
- **Check the blackboard** for `api-access` tagged experiences to see if the current repo has confirmed API access
|
|
310
|
+
- **If access is confirmed**: Note which APIs are available and prefer direct API calls over browser automation
|
|
311
|
+
- **If no access experience exists**: Default to browser automation or MCP tools
|
|
312
|
+
- **Always document**: Which APIs are used, what credentials are needed, what repo provides the client libraries
|
|
312
313
|
|
|
313
314
|
This prevents future sessions from trying to use APIs they don't have access to.
|
|
314
315
|
|
|
@@ -57,7 +57,7 @@ Orient must know the available MCPs and their contextual triggers.
|
|
|
57
57
|
Use the smallest relevant MCP set.
|
|
58
58
|
|
|
59
59
|
- Jira issue key or Atlassian URL -> `mcp-atlassian-personal` (or the configured personal account name)
|
|
60
|
-
- "internal docs", "runbook", "
|
|
60
|
+
- "internal docs", "runbook", "company wiki", "Glean" -> `glean_default`
|
|
61
61
|
- "how do I use X library" -> `context7`
|
|
62
62
|
- "calendar", "meeting", "free time" -> `google-calendar`
|
|
63
63
|
- "Slack", "channel", "thread", "notify" -> `slack`
|
|
@@ -197,7 +197,45 @@ When asking, ask one focused question with concrete choices.
|
|
|
197
197
|
- **Just do the thing.** If the credentials don't work, you'll find out when the API call fails — and that's a better signal than a speculative question.
|
|
198
198
|
4. If no matching experience exists, proceed with asking.
|
|
199
199
|
|
|
200
|
-
This rule exists because users set up repo-level context once (e.g., "
|
|
200
|
+
This rule exists because users set up repo-level context once (e.g., "my-tools repo has full API access to our admin systems") and expect Claude to remember it across every session. Asking "do you have admin access?" when the blackboard already says "yes, full access" is the #1 frustration signal.
|
|
201
|
+
|
|
202
|
+
### Access Declaration Detection (MANDATORY)
|
|
203
|
+
|
|
204
|
+
When a user declares repo-level access — either explicitly or as part of a task — **immediately write a blackboard experience so it persists across sessions.** Do NOT wait until the task is complete. Write it during Orient, before acting.
|
|
205
|
+
|
|
206
|
+
**Detection triggers** (any of these in the user's message):
|
|
207
|
+
- "I have access to...", "I have credentials for...", "I'm authenticated to..."
|
|
208
|
+
- "this repo has access to...", "we have API keys for..."
|
|
209
|
+
- "just do it, I have the creds", "you have access here", "credentials are configured"
|
|
210
|
+
- "I'm in [repo name] with my credentials"
|
|
211
|
+
- The user tells you to stop asking and just use an API
|
|
212
|
+
- An API call succeeds for the first time in a repo where no access experience exists
|
|
213
|
+
|
|
214
|
+
**What to write** — create an experience file at `~/.claude/ftm-state/blackboard/experiences/learning-{repo-name}-api-access.json`:
|
|
215
|
+
|
|
216
|
+
```json
|
|
217
|
+
{
|
|
218
|
+
"id": "learning-{repo-name}-api-access",
|
|
219
|
+
"timestamp": "{ISO 8601 now}",
|
|
220
|
+
"task_type": "environment-knowledge",
|
|
221
|
+
"tags": ["{repo-name}", "api-access", "environment", "learning"],
|
|
222
|
+
"outcome": "success",
|
|
223
|
+
"description": "User confirmed API access in {repo-name} repo. {any specifics they mentioned — which systems, what kind of access}.",
|
|
224
|
+
"lessons": [
|
|
225
|
+
"{repo-name} repo has configured access to {systems mentioned}",
|
|
226
|
+
"Do not ask about credentials or authorization when working in this repo — just act"
|
|
227
|
+
],
|
|
228
|
+
"confidence": 1.0,
|
|
229
|
+
"code_patterns": [],
|
|
230
|
+
"api_gotchas": []
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Also update `experiences/index.json` with the new entry.
|
|
235
|
+
|
|
236
|
+
**On first successful API call:** If you make an API call in a repo and it succeeds, but no access experience exists for this repo, write one automatically. The success IS the proof of access. Tag it with the repo name and the system that worked (e.g., `freshservice`, `okta`).
|
|
237
|
+
|
|
238
|
+
**This is not optional.** Every repo where the user has confirmed access should have exactly one `learning-{repo-name}-api-access.json` experience. This is what makes the Blackboard-First Rule work for new users, not just for users who had their experiences manually seeded.
|
|
201
239
|
|
|
202
240
|
### Discovery Interview (medium+ tasks with external systems)
|
|
203
241
|
|
|
@@ -1,26 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"current_task": {
|
|
3
|
-
"id":
|
|
4
|
-
"description":
|
|
5
|
-
"type":
|
|
6
|
-
"started_at":
|
|
7
|
-
"status": "
|
|
8
|
-
"next_action":
|
|
3
|
+
"id": null,
|
|
4
|
+
"description": null,
|
|
5
|
+
"type": null,
|
|
6
|
+
"started_at": null,
|
|
7
|
+
"status": "none",
|
|
8
|
+
"next_action": null
|
|
9
9
|
},
|
|
10
|
-
"recent_decisions": [
|
|
11
|
-
{
|
|
12
|
-
"decision": "Used GitHub Pages with static HTML instead of a framework",
|
|
13
|
-
"reason": "Simple, fast deployment for hackathon team reference pages"
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
"decision": "Restored full docx content into playbook.html while keeping coffee-shop design",
|
|
17
|
-
"reason": "HTML version had trimmed role descriptions — docx had the complete detail"
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
"decision": "Fixed flow.html by porting missing elements from agent-flow-map.html",
|
|
21
|
-
"reason": "Node overlap, missing transcript node, chat bubbles, and annotations"
|
|
22
|
-
}
|
|
23
|
-
],
|
|
10
|
+
"recent_decisions": [],
|
|
24
11
|
"active_constraints": [],
|
|
25
12
|
"user_preferences": {
|
|
26
13
|
"communication_style": "concise, technical",
|
|
@@ -28,10 +15,10 @@
|
|
|
28
15
|
"default_model_profile": null
|
|
29
16
|
},
|
|
30
17
|
"session_metadata": {
|
|
31
|
-
"started_at":
|
|
32
|
-
"last_updated":
|
|
18
|
+
"started_at": null,
|
|
19
|
+
"last_updated": null,
|
|
33
20
|
"conversation_id": null,
|
|
34
|
-
"messages_count":
|
|
21
|
+
"messages_count": 0,
|
|
35
22
|
"skills_invoked": []
|
|
36
23
|
}
|
|
37
24
|
}
|
|
@@ -1,57 +1,8 @@
|
|
|
1
1
|
{
|
|
2
|
-
"entries": [
|
|
3
|
-
{
|
|
4
|
-
"id": "nordlayer-members-auto-assign",
|
|
5
|
-
"file": "nordlayer-members-auto-assign.json",
|
|
6
|
-
"timestamp": "2026-03-19T11:00:00Z",
|
|
7
|
-
"task_type": "freshservice-workflow-routing",
|
|
8
|
-
"outcome": "success",
|
|
9
|
-
"tags": ["freshservice", "nordlayer", "custom-trigger", "approval-bypass", "lambda"]
|
|
10
|
-
},
|
|
11
|
-
{
|
|
12
|
-
"id": "hindsight-sso-kickoff",
|
|
13
|
-
"file": "hindsight-sso-kickoff.json",
|
|
14
|
-
"timestamp": "2026-03-20T08:30:00Z",
|
|
15
|
-
"task_type": "sso-implementation",
|
|
16
|
-
"outcome": "in_progress",
|
|
17
|
-
"tags": ["sso", "saml", "okta", "hindsight", "vendor-unblock", "planning"]
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
"id": "learning-ragnarok-api-access",
|
|
21
|
-
"file": "learning-ragnarok-api-access.json",
|
|
22
|
-
"timestamp": "2026-03-20T08:40:00Z",
|
|
23
|
-
"task_type": "environment-knowledge",
|
|
24
|
-
"outcome": "success",
|
|
25
|
-
"tags": ["ragnarok", "okta", "api-access", "environment", "learning"]
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
"id": "doom-statusline-fix",
|
|
29
|
-
"file": "doom-statusline-fix.json",
|
|
30
|
-
"timestamp": "2026-03-22T00:00:00Z",
|
|
31
|
-
"task_type": "developer-tooling",
|
|
32
|
-
"outcome": "success",
|
|
33
|
-
"tags": ["statusline", "doom-hud", "terminal", "claude-code", "ansi"]
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
"id": "hackathon-pages-site",
|
|
37
|
-
"file": "hackathon-pages-site.json",
|
|
38
|
-
"timestamp": "2026-03-23T00:00:00Z",
|
|
39
|
-
"task_type": "hackathon-prep",
|
|
40
|
-
"outcome": "success",
|
|
41
|
-
"tags": ["github-pages", "hackathon", "static-html", "team-site", "onboarding"]
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
"id": "saml2aws-stale-session-fix",
|
|
45
|
-
"file": "saml2aws-stale-session-fix.json",
|
|
46
|
-
"timestamp": "2026-03-24T00:00:00Z",
|
|
47
|
-
"task_type": "troubleshooting",
|
|
48
|
-
"outcome": "success",
|
|
49
|
-
"tags": ["saml2aws", "okta", "aws", "browser-provider", "session-cache", "authentication"]
|
|
50
|
-
}
|
|
51
|
-
],
|
|
2
|
+
"entries": [],
|
|
52
3
|
"metadata": {
|
|
53
|
-
"total_count":
|
|
54
|
-
"last_updated":
|
|
4
|
+
"total_count": 0,
|
|
5
|
+
"last_updated": null,
|
|
55
6
|
"max_entries": 200,
|
|
56
7
|
"pruning_strategy": "remove_oldest_low_confidence"
|
|
57
8
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "feed-the-machine",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.6",
|
|
4
4
|
"description": "A brain upgrade for Claude Code — 26 skills that teach it how to think before acting, remember across conversations, debug like a war room, run plans on autopilot with agent teams, and get second opinions from GPT & Gemini. Plus 15 hooks that automate the boring stuff.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "kkudumu",
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"id": "doom-statusline-fix",
|
|
3
|
-
"task_type": "developer-tooling",
|
|
4
|
-
"tags": ["statusline", "doom-hud", "terminal", "claude-code", "ansi"],
|
|
5
|
-
"outcome": "success",
|
|
6
|
-
"timestamp": "2026-03-22T00:00:00Z",
|
|
7
|
-
"lessons": [
|
|
8
|
-
"Non-Warp statusline path loads ANSI face art by default — disable by skipping the ansi_faces.json load",
|
|
9
|
-
"MOOD label (IDDQD etc) is appended in both the overlay state and the Row 3 printf — both need removal",
|
|
10
|
-
"statusline-setup agent type exists for this kind of work"
|
|
11
|
-
],
|
|
12
|
-
"files_touched": [
|
|
13
|
-
"~/.claude/scripts/doom-statusline.sh"
|
|
14
|
-
],
|
|
15
|
-
"stakeholders": [],
|
|
16
|
-
"decisions_made": [
|
|
17
|
-
{
|
|
18
|
-
"decision": "Disabled ANSI face loading for non-Warp/non-Kitty terminals",
|
|
19
|
-
"reason": "User wants clean powerline segments, not pixel art"
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
"decision": "Removed MOOD text from Row 3 output and overlay state",
|
|
23
|
-
"reason": "Matches desired Warp-style layout"
|
|
24
|
-
}
|
|
25
|
-
]
|
|
26
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"id": "hackathon-pages-site",
|
|
3
|
-
"timestamp": "2026-03-23T00:00:00Z",
|
|
4
|
-
"task_type": "hackathon-prep",
|
|
5
|
-
"tags": ["github-pages", "hackathon", "static-html", "team-site", "onboarding"],
|
|
6
|
-
"outcome": "success",
|
|
7
|
-
"lessons": [
|
|
8
|
-
"GitHub Pages with build_type workflow needs a .github/workflows/pages.yml to deploy",
|
|
9
|
-
"When porting design between themes, check for missing nodes/paths/annotations — AI generators often drop elements",
|
|
10
|
-
"Docx content can be extracted with Python zipfile + xml.etree for comparison against HTML versions"
|
|
11
|
-
],
|
|
12
|
-
"files_touched": [
|
|
13
|
-
"index.html",
|
|
14
|
-
"playbook.html",
|
|
15
|
-
"flow.html",
|
|
16
|
-
"agent-flow-map.html",
|
|
17
|
-
"agent-flow.html",
|
|
18
|
-
".github/workflows/pages.yml"
|
|
19
|
-
],
|
|
20
|
-
"stakeholders": ["hackathon team"],
|
|
21
|
-
"decisions_made": [
|
|
22
|
-
"Static HTML on GitHub Pages — no framework needed for reference pages",
|
|
23
|
-
"Kept coffee-shop design theme across all pages",
|
|
24
|
-
"Wired all homepage links to actual pages including Slack and GitHub repo"
|
|
25
|
-
]
|
|
26
|
-
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"id": "hindsight-sso-kickoff",
|
|
3
|
-
"timestamp": "2026-03-20T08:30:00Z",
|
|
4
|
-
"task_type": "sso-implementation",
|
|
5
|
-
"tags": ["sso", "saml", "okta", "hindsight", "vendor-unblock", "planning"],
|
|
6
|
-
"outcome": "in_progress",
|
|
7
|
-
"description": "Hindsight SSO blocker cleared - Ani provided ACS URL + Entity ID. Fetched vendor docs, confirmed SAML 2.0 setup. Created execution plan. Awaiting user decision on browser automation vs manual Okta setup.",
|
|
8
|
-
"lessons": [
|
|
9
|
-
"Hindsight uses Clerk for SAML - ACS URL and Entity ID both under clerk.usehindsight.com domain",
|
|
10
|
-
"SAML only - no OIDC support for Okta",
|
|
11
|
-
"Required attributes: mail, firstName, lastName (standard Okta mappings)",
|
|
12
|
-
"Name ID format: EmailAddress",
|
|
13
|
-
"Post-config: vendor needs Okta Metadata URL to finalize their side",
|
|
14
|
-
"No SCIM - user management is manual/Okta groups only",
|
|
15
|
-
"Approval owner: Mindy Regnell (CI team)",
|
|
16
|
-
"Multiple permission levels exist but details not yet mapped to Okta groups"
|
|
17
|
-
],
|
|
18
|
-
"files_touched": [
|
|
19
|
-
"~/.claude/eng-buddy/daily/2026-03-20.md",
|
|
20
|
-
"~/.claude/eng-buddy/daily/daily-index.md",
|
|
21
|
-
"~/.claude/ftm-state/blackboard/context.json"
|
|
22
|
-
],
|
|
23
|
-
"stakeholders": {
|
|
24
|
-
"requester": "Alani Setalsingh",
|
|
25
|
-
"vendor_poc": "Ani Gottiparthy (Ani@usehindsight.com)",
|
|
26
|
-
"approval_owner": "Mindy Regnell",
|
|
27
|
-
"initial_users": ["Mindy.Regnell@klaviyo.com", "mokhsira.kurbonova@klaviyo.com", "anvi.vasa@klaviyo.com"]
|
|
28
|
-
},
|
|
29
|
-
"decisions_made": [
|
|
30
|
-
{
|
|
31
|
-
"decision": "Confirmed SAML 2.0 app type (not OIDC) based on vendor docs",
|
|
32
|
-
"reason": "Hindsight/Clerk explicitly does not support OIDC for Okta"
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
"decision": "Identified need for Okta groups based on multiple permission levels",
|
|
36
|
-
"reason": "Ticket states different permission levels exist - need to map before group creation"
|
|
37
|
-
}
|
|
38
|
-
],
|
|
39
|
-
"jira_key": "ITWORK2-9702",
|
|
40
|
-
"freshservice_ticket": "321024",
|
|
41
|
-
"confidence": 0.9
|
|
42
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"id": "learning-ragnarok-api-access",
|
|
3
|
-
"timestamp": "2026-03-20T08:40:00Z",
|
|
4
|
-
"task_type": "environment-knowledge",
|
|
5
|
-
"tags": ["ragnarok", "okta", "api-access", "environment", "learning"],
|
|
6
|
-
"outcome": "success",
|
|
7
|
-
"description": "When working in ~/Documents/Code/ragnarok, we have full environment API access to all integrated systems (Okta, Freshservice, Jira, etc.) via shared_services. Always prefer API calls over browser automation when in this repo.",
|
|
8
|
-
"lessons": [
|
|
9
|
-
"~/Documents/Code/ragnarok has shared_services with API clients for Okta, Freshservice, Slack, Jamf, Google, etc.",
|
|
10
|
-
"Always prefer API over browser automation when in ragnarok repo - faster, more reliable, scriptable",
|
|
11
|
-
"Okta API access available via shared_services/okta/",
|
|
12
|
-
"Secrets stored in AWS Secrets Manager, retrieved at runtime"
|
|
13
|
-
],
|
|
14
|
-
"files_touched": [],
|
|
15
|
-
"stakeholders": {},
|
|
16
|
-
"decisions_made": [
|
|
17
|
-
{
|
|
18
|
-
"decision": "Use Okta API directly instead of browser automation for SSO app creation",
|
|
19
|
-
"reason": "ragnarok repo has full Okta API access via shared_services - faster and more reliable than playwright"
|
|
20
|
-
}
|
|
21
|
-
],
|
|
22
|
-
"confidence": 1.0
|
|
23
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"id": "nordlayer-members-auto-assign",
|
|
3
|
-
"timestamp": "2026-03-19T11:00:00Z",
|
|
4
|
-
"task_type": "freshservice-workflow-routing",
|
|
5
|
-
"tags": ["freshservice", "nordlayer", "custom-trigger", "approval-bypass", "lambda"],
|
|
6
|
-
"outcome": "success",
|
|
7
|
-
"confidence": 0.95,
|
|
8
|
-
"summary": "Added auto_assign_upon_request routing for Nordlayer Members role in freshservice_workflow_assigner Lambda, bypassing app owner approval while keeping Administrator and Owner roles unchanged.",
|
|
9
|
-
"lessons": [
|
|
10
|
-
"The freshservice_workflow_assigner Lambda is the single router for all custom triggers - always modify it rather than creating separate Lambdas for per-app routing",
|
|
11
|
-
"Custom trigger format is {workflow}:{role} - the Freshservice Automator matches on the workflow prefix to determine which workflow runs",
|
|
12
|
-
"auto_assign_upon_request is the existing trigger name for auto-approve workflows",
|
|
13
|
-
"Custom object 15000002166 stores per-app role metadata including approvers - query it to verify role names and approver state",
|
|
14
|
-
"Nordlayer role names are: Members, Administrator, Owner (title case, not snake_case like Lusha)",
|
|
15
|
-
"Deploy flow: push to main -> CI/CD auto-packages -> Lambda picks up new code from S3"
|
|
16
|
-
],
|
|
17
|
-
"files_touched": [
|
|
18
|
-
"lambda/handlers/freshservice_workflow_assigner/app.py"
|
|
19
|
-
],
|
|
20
|
-
"stakeholders": ["kioja.kudumu"],
|
|
21
|
-
"decisions_made": [
|
|
22
|
-
"Used tuple-keyed dict (app_name, role) for override matching to avoid cross-app side effects",
|
|
23
|
-
"Kept change in existing Lambda rather than creating nordlayer-specific handler",
|
|
24
|
-
"PR #1313 created on feature/nordlayer-members-auto-assign branch"
|
|
25
|
-
]
|
|
26
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"id": "saml2aws-stale-session-fix",
|
|
3
|
-
"title": "saml2aws login fails with 'Invalid role string only 0 tokens' due to stale browser session cache",
|
|
4
|
-
"created": "2026-03-24",
|
|
5
|
-
"category": "troubleshooting",
|
|
6
|
-
"tags": ["saml2aws", "okta", "aws", "browser-provider", "session-cache", "authentication"],
|
|
7
|
-
"summary": "saml2aws login with Browser provider instantly opens and closes browser (~2 seconds) without showing Okta login page, then fails with 'Error parsing AWS roles.: Invalid role string only 0 tokens'. Root cause is stale cached browser session files that replay an expired/invalid Okta session instead of prompting for fresh authentication.",
|
|
8
|
-
"symptoms": [
|
|
9
|
-
"Browser opens and closes in ~2 seconds without showing login page",
|
|
10
|
-
"Error: 'Failed to assume role. Please check whether you are permitted to assume the given role for the AWS service.: Error parsing AWS roles.: Invalid role string only 0 tokens'",
|
|
11
|
-
"Same error with --force, --disable-sessions, --disable-keychain flags",
|
|
12
|
-
"Reinstalling saml2aws does not fix the issue"
|
|
13
|
-
],
|
|
14
|
-
"root_cause": "Stale storageState.json and cache_default files in ~/.aws/saml2aws/ cause the Browser provider to replay a cached Okta session that returns an empty SAML response (no AWS role attributes), bypassing the interactive login entirely.",
|
|
15
|
-
"fix": {
|
|
16
|
-
"steps": [
|
|
17
|
-
"Back up stale session files: mv ~/.aws/saml2aws/storageState.json ~/.aws/saml2aws/storageState.json.bak",
|
|
18
|
-
"Back up cache file: mv ~/.aws/saml2aws/cache_default ~/.aws/saml2aws/cache_default.bak",
|
|
19
|
-
"Set disable_sessions = true in ~/.saml2aws config",
|
|
20
|
-
"Run: saml2aws login --verbose --force"
|
|
21
|
-
],
|
|
22
|
-
"key_files": [
|
|
23
|
-
"~/.aws/saml2aws/storageState.json",
|
|
24
|
-
"~/.aws/saml2aws/cache_default",
|
|
25
|
-
"~/.saml2aws"
|
|
26
|
-
],
|
|
27
|
-
"nuclear_option": "rm -rf ~/.aws/saml2aws/storageState.json ~/.aws/saml2aws/cache_default && saml2aws login --force --disable-sessions --disable-keychain"
|
|
28
|
-
},
|
|
29
|
-
"lessons_learned": [
|
|
30
|
-
"Always check for stale session cache files BEFORE reinstalling saml2aws",
|
|
31
|
-
"The Browser provider stores Playwright session state in ~/.aws/saml2aws/storageState.json — this is the #1 cause of instant-close browser behavior",
|
|
32
|
-
"Reinstalling saml2aws or switching versions does NOT clear session cache files",
|
|
33
|
-
"Klaviyo uses saml2aws 2.36.17 from klaviyo-third-party-prod.s3.amazonaws.com, not the brew version",
|
|
34
|
-
"klaviyocli config saml2aws is the official way to configure at Klaviyo, but manual config works if klaviyocli is not installed"
|
|
35
|
-
],
|
|
36
|
-
"related_docs": [
|
|
37
|
-
"https://klaviyo.atlassian.net/wiki/spaces/IT/pages/3531800639 (KlaviyoCLI setup for Okta MFA)",
|
|
38
|
-
"https://klaviyo.atlassian.net/wiki/spaces/BI/pages/3447980089 (AWS Local Setup)",
|
|
39
|
-
"https://klaviyo.atlassian.net/wiki/spaces/IT/pages/3574661289 (Ragnarok)"
|
|
40
|
-
]
|
|
41
|
-
}
|