@northbridge-security/secureai 0.1.13

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.
Files changed (50) hide show
  1. package/.claude/README.md +122 -0
  2. package/.claude/commands/architect/clean.md +978 -0
  3. package/.claude/commands/architect/kiss.md +762 -0
  4. package/.claude/commands/architect/review.md +704 -0
  5. package/.claude/commands/catchup.md +90 -0
  6. package/.claude/commands/code.md +115 -0
  7. package/.claude/commands/commit.md +1218 -0
  8. package/.claude/commands/cover.md +1298 -0
  9. package/.claude/commands/fmea.md +275 -0
  10. package/.claude/commands/kaizen.md +312 -0
  11. package/.claude/commands/pr.md +503 -0
  12. package/.claude/commands/todo.md +99 -0
  13. package/.claude/commands/worktree.md +738 -0
  14. package/.claude/commands/wrapup.md +103 -0
  15. package/LICENSE +183 -0
  16. package/README.md +108 -0
  17. package/dist/cli.js +75634 -0
  18. package/docs/agents/devops-reviewer.md +889 -0
  19. package/docs/agents/kiss-simplifier.md +1088 -0
  20. package/docs/agents/typescript.md +8 -0
  21. package/docs/guides/README.md +109 -0
  22. package/docs/guides/agents.clean.arch.md +244 -0
  23. package/docs/guides/agents.clean.arch.ts.md +1314 -0
  24. package/docs/guides/agents.gotask.md +1037 -0
  25. package/docs/guides/agents.markdown.md +1209 -0
  26. package/docs/guides/agents.onepassword.md +285 -0
  27. package/docs/guides/agents.sonar.md +857 -0
  28. package/docs/guides/agents.tdd.md +838 -0
  29. package/docs/guides/agents.tdd.ts.md +1062 -0
  30. package/docs/guides/agents.typesript.md +1389 -0
  31. package/docs/guides/github-mcp.md +1075 -0
  32. package/package.json +130 -0
  33. package/packages/secureai-cli/src/cli.ts +21 -0
  34. package/tasks/README.md +880 -0
  35. package/tasks/aws.yml +64 -0
  36. package/tasks/bash.yml +118 -0
  37. package/tasks/bun.yml +738 -0
  38. package/tasks/claude.yml +183 -0
  39. package/tasks/docker.yml +420 -0
  40. package/tasks/docs.yml +127 -0
  41. package/tasks/git.yml +1336 -0
  42. package/tasks/gotask.yml +132 -0
  43. package/tasks/json.yml +77 -0
  44. package/tasks/markdown.yml +95 -0
  45. package/tasks/onepassword.yml +350 -0
  46. package/tasks/security.yml +102 -0
  47. package/tasks/sonar.yml +437 -0
  48. package/tasks/template.yml +74 -0
  49. package/tasks/vscode.yml +103 -0
  50. package/tasks/yaml.yml +121 -0
@@ -0,0 +1,132 @@
1
+ # GoTask Development Utilities
2
+ # Tools and cookie cutters for coding, testing, and maintaining task files
3
+
4
+ version: "3"
5
+
6
+ tasks:
7
+ default:
8
+ desc: "Show available GoTask utilities"
9
+ aliases: [help, h]
10
+ silent: true
11
+ cmds:
12
+ - |
13
+ # Color codes
14
+ GREEN='\033[0;32m'
15
+ YELLOW='\033[0;33m'
16
+ BOLD='\033[1m'
17
+ NC='\033[0m'
18
+
19
+ echo -e "${BOLD}GoTask Development Utilities${NC}"
20
+ echo ""
21
+ echo "Command Alias Description Examples"
22
+ echo "───────────────────────────────────────────────────────────────────────────────────────────────────"
23
+ echo -e "${BOLD}Task Development:${NC}"
24
+ echo -e " ${GREEN}task gotask:format${NC} ${YELLOW}f${NC} Format default task in Taskfile"
25
+ echo -e " ${GREEN}task gotask:new:task${NC} ${YELLOW}nt${NC} Create new task in Taskfile.yml"
26
+ echo -e " ${GREEN}task gotask:new:script${NC} ${YELLOW}ns${NC} Create new TypeScript task script"
27
+ echo -e " ${GREEN}task gotask:validate${NC} ${YELLOW}v${NC} Validate all Taskfile.yml syntax"
28
+ echo -e " ${GREEN}task gotask:deps:check${NC} ${YELLOW}dc${NC} Check for missing task dependencies"
29
+ echo ""
30
+ echo -e "${BOLD}Setup & Configuration:${NC}"
31
+ echo -e " ${GREEN}task gotask:setup:extensions${NC} ${YELLOW}se${NC} Install recommended VSCode extensions"
32
+ echo ""
33
+ echo -e "${BOLD}Documentation:${NC}"
34
+ echo -e " ${GREEN}task gotask:docs:generate${NC} ${YELLOW}dg${NC} Generate task documentation"
35
+ echo -e " ${GREEN}task gotask:docs:view${NC} ${YELLOW}dv${NC} View best practices guide"
36
+ echo -e " ${GREEN}task gotask:docs:edit${NC} ${YELLOW}de${NC} Edit best practices guide"
37
+ echo ""
38
+ echo -e "${BOLD}Templates:${NC}"
39
+ echo -e " ${GREEN}task gotask:template:basic${NC} ${YELLOW}tb${NC} Generate basic task template"
40
+ echo -e " ${GREEN}task gotask:template:build${NC} ${YELLOW}tbu${NC} Generate build task template"
41
+ echo -e " ${GREEN}task gotask:template:test${NC} ${YELLOW}tt${NC} Generate test task template"
42
+
43
+ format:
44
+ desc: Format default task in Taskfile
45
+ aliases: [f]
46
+ silent: true
47
+ cmds:
48
+ - bun run {{.TASKFILE_DIR}}/../src/tasks/gotask/format-default.ts {{.CLI_ARGS}}
49
+
50
+ new:task:
51
+ desc: Create a new task in Taskfile.yml
52
+ aliases: [nt]
53
+ silent: true
54
+ cmds:
55
+ - bun run {{.TASKFILE_DIR}}/../src/tasks/gotask/new-task.ts {{.CLI_ARGS}}
56
+
57
+ new:script:
58
+ desc: Create a new TypeScript task script
59
+ aliases: [ns]
60
+ silent: true
61
+ cmds:
62
+ - bun run {{.TASKFILE_DIR}}/../src/tasks/gotask/new-script.ts {{.CLI_ARGS}}
63
+
64
+ validate:
65
+ desc: Validate all Taskfile.yml syntax
66
+ aliases: [v]
67
+ silent: true
68
+ cmds:
69
+ - bun run {{.TASKFILE_DIR}}/../src/tasks/gotask/validate-taskfiles.ts
70
+
71
+ deps:check:
72
+ desc: Check for missing task dependencies
73
+ aliases: [dc]
74
+ silent: true
75
+ cmds:
76
+ - bun run {{.TASKFILE_DIR}}/../src/tasks/gotask/check-deps.ts
77
+
78
+ setup:extensions:
79
+ desc: Install recommended VSCode/Cursor extensions
80
+ aliases: [se]
81
+ silent: true
82
+ cmds:
83
+ - bun run {{.TASKFILE_DIR}}/../src/tasks/gotask/setup-vscode-extensions.ts
84
+
85
+ docs:generate:
86
+ desc: Generate task documentation
87
+ aliases: [dg]
88
+ silent: true
89
+ cmds:
90
+ - bun run {{.TASKFILE_DIR}}/../src/tasks/gotask/generate-docs.ts
91
+
92
+ docs:view:
93
+ desc: View gotask best practices guide
94
+ aliases: [dv]
95
+ silent: true
96
+ cmds:
97
+ - |
98
+ if command -v bat &> /dev/null; then
99
+ bat src/tasks/gotask/docs/best-practices.md
100
+ elif command -v less &> /dev/null; then
101
+ less src/tasks/gotask/docs/best-practices.md
102
+ else
103
+ cat src/tasks/gotask/docs/best-practices.md
104
+ fi
105
+
106
+ docs:edit:
107
+ desc: Edit gotask best practices guide
108
+ aliases: [de]
109
+ silent: true
110
+ cmds:
111
+ - ${EDITOR:-code} src/tasks/gotask/docs/best-practices.md
112
+
113
+ template:basic:
114
+ desc: Generate basic task template
115
+ aliases: [tb]
116
+ silent: true
117
+ cmds:
118
+ - bun run {{.TASKFILE_DIR}}/../src/tasks/gotask/templates/basic.ts {{.CLI_ARGS}}
119
+
120
+ template:build:
121
+ desc: Generate build task template
122
+ aliases: [tbu]
123
+ silent: true
124
+ cmds:
125
+ - bun run {{.TASKFILE_DIR}}/../src/tasks/gotask/templates/build.ts {{.CLI_ARGS}}
126
+
127
+ template:test:
128
+ desc: Generate test task template
129
+ aliases: [tt]
130
+ silent: true
131
+ cmds:
132
+ - bun run {{.TASKFILE_DIR}}/../src/tasks/gotask/templates/test.ts {{.CLI_ARGS}}
package/tasks/json.yml ADDED
@@ -0,0 +1,77 @@
1
+ # JSON Linting, Parsing & Validation Tasks
2
+ # Provides JSON linting, parsing, schema validation and common operations
3
+
4
+ version: "3"
5
+
6
+ vars:
7
+ DEFAULT_PATTERNS: "*.json,**/*.json,!node_modules/**,!dist/**,!.taskmaster/**"
8
+
9
+ tasks:
10
+ default:
11
+ desc: "Show available JSON tasks"
12
+ aliases: [help, h]
13
+ silent: true
14
+ cmds:
15
+ - |
16
+ # Color codes
17
+ GREEN='\033[0;32m'
18
+ YELLOW='\033[0;33m'
19
+ BOLD='\033[1m'
20
+ NC='\033[0m'
21
+
22
+ echo -e "${BOLD}JSON Linting, Parsing & Validation${NC}"
23
+ echo ""
24
+ echo "Command Alias Description Examples"
25
+ echo "───────────────────────────────────────────────────────────────────────────────────────────────────"
26
+ echo -e " ${GREEN}task json:lint${NC} ${YELLOW}l${NC} Lint JSON files FILES=\"*.json\""
27
+ echo -e " ${GREEN}task json:lint:fix${NC} ${YELLOW}lf${NC} Auto-fix JSON formatting FILES=\"*.json\""
28
+ echo ""
29
+ echo -e "${BOLD}Usage Examples:${NC}"
30
+ echo -e " task json:lint Lint all JSON files (quiet on success)"
31
+ echo -e " task json:lint FILES=\"*.json\" Lint specific pattern"
32
+ echo -e " VERBOSE=1 task json:lint Show output even on success"
33
+ echo -e " task json:lint:fix Auto-fix all issues"
34
+
35
+ lint:
36
+ desc: "Lint JSON files (quiet on success, use VERBOSE=1 for details)"
37
+ aliases: [l]
38
+ silent: true
39
+ vars:
40
+ FILE_PATTERNS: "{{.FILES | default .DEFAULT_PATTERNS}}"
41
+ VERBOSE_FLAG: '{{.VERBOSE | default ""}}'
42
+ cmds:
43
+ - |
44
+ REPO_URL=$(task git:repo:url 2>/dev/null || echo "")
45
+ SCRIPT="{{.TASKFILE_DIR}}/../src/tasks/json/lint.ts"
46
+
47
+ if [ "$REPO_URL" = "https://github.com/northbridge-security/ai-toolkit" ] && [ -f "$SCRIPT" ]; then
48
+ bun run "$SCRIPT"
49
+ else
50
+ # Fallback to ai-toolkit CLI
51
+ npx @northbridge-security/ai-toolkit json lint -f "$FILES"
52
+ fi
53
+ env:
54
+ FILES: "{{.FILE_PATTERNS}}"
55
+ VERBOSE: "{{.VERBOSE_FLAG}}"
56
+
57
+ lint:fix:
58
+ desc: "Auto-fix JSON formatting (pretty-print with 2-space indent)"
59
+ aliases: [lf, fix]
60
+ silent: true
61
+ vars:
62
+ FILE_PATTERNS: "{{.FILES | default .DEFAULT_PATTERNS}}"
63
+ VERBOSE_FLAG: '{{.VERBOSE | default ""}}'
64
+ cmds:
65
+ - |
66
+ REPO_URL=$(task git:repo:url 2>/dev/null || echo "")
67
+ SCRIPT="{{.TASKFILE_DIR}}/../src/tasks/json/lint-fix.ts"
68
+
69
+ if [ "$REPO_URL" = "https://github.com/northbridge-security/ai-toolkit" ] && [ -f "$SCRIPT" ]; then
70
+ bun run "$SCRIPT"
71
+ else
72
+ # Fallback to ai-toolkit CLI
73
+ npx @northbridge-security/ai-toolkit json lint --fix -f "$FILES"
74
+ fi
75
+ env:
76
+ FILES: "{{.FILE_PATTERNS}}"
77
+ VERBOSE: "{{.VERBOSE_FLAG}}"
@@ -0,0 +1,95 @@
1
+ # Markdown Linting & Validation Tasks
2
+ # Provides markdown validation, linting, and auto-fixing for all markdown files in the project.
3
+
4
+ version: "3"
5
+
6
+ vars:
7
+ DEFAULT_PATTERNS: "*.md,docs/**/*.md,.github/**/*.md,tasks/**/*.md"
8
+ MARKDOWNLINT_CONFIG: ".markdownlint.yaml"
9
+
10
+ tasks:
11
+ default:
12
+ desc: "Show available Markdown tasks"
13
+ aliases: [help, h]
14
+ silent: true
15
+ cmds:
16
+ - |
17
+ # Color codes
18
+ GREEN='\033[0;32m'
19
+ YELLOW='\033[0;33m'
20
+ BOLD='\033[1m'
21
+ NC='\033[0m'
22
+
23
+ echo -e "${BOLD}Markdown Linting & Validation${NC}"
24
+ echo ""
25
+ echo "Command Alias Description Examples"
26
+ echo "───────────────────────────────────────────────────────────────────────────────────────────────────"
27
+ echo -e " ${GREEN}task markdown:lint${NC} ${YELLOW}l${NC} Lint markdown files FILES=\"*.md\""
28
+ echo -e " ${GREEN}task markdown:lint:fix${NC} ${YELLOW}lf${NC} Auto-fix markdown formatting FILES=\"*.md\""
29
+ echo -e " ${GREEN}task markdown:setup${NC} ${YELLOW}s${NC} Install markdownlint & create config"
30
+ echo ""
31
+ echo -e "${BOLD}Usage Examples:${NC}"
32
+ echo -e " task markdown:lint # Lint all markdown files (quiet on success)"
33
+ echo -e " task markdown:lint FILES=\"*.md\" # Lint specific pattern"
34
+ echo -e " VERBOSE=1 task markdown:lint # Show output even on success"
35
+ echo -e " task markdown:lint:fix # Auto-fix all issues"
36
+
37
+ lint:
38
+ desc: "Lint markdown files (quiet on success, use VERBOSE=1 for details)"
39
+ aliases: [l]
40
+ silent: true
41
+ vars:
42
+ FILE_PATTERNS: "{{.FILES | default .DEFAULT_PATTERNS}}"
43
+ VERBOSE_FLAG: '{{.VERBOSE | default ""}}'
44
+ cmds:
45
+ - |
46
+ REPO_URL=$(task git:repo:url 2>/dev/null || echo "")
47
+ SCRIPT="{{.TASKFILE_DIR}}/../src/tasks/markdown/lint.ts"
48
+
49
+ if [ "$REPO_URL" = "https://github.com/northbridge-security/ai-toolkit" ] && [ -f "$SCRIPT" ]; then
50
+ bun run "$SCRIPT"
51
+ else
52
+ # Fallback to ai-toolkit CLI
53
+ npx @northbridge-security/ai-toolkit markdown lint -f "$FILES"
54
+ fi
55
+ env:
56
+ FILES: "{{.FILE_PATTERNS}}"
57
+ VERBOSE: "{{.VERBOSE_FLAG}}"
58
+
59
+ lint:fix:
60
+ desc: "Auto-fix markdown files where possible (quiet when no changes)"
61
+ aliases: [lf, fix]
62
+ silent: true
63
+ vars:
64
+ FILE_PATTERNS: "{{.FILES | default .DEFAULT_PATTERNS}}"
65
+ VERBOSE_FLAG: '{{.VERBOSE | default ""}}'
66
+ cmds:
67
+ - |
68
+ REPO_URL=$(task git:repo:url 2>/dev/null || echo "")
69
+ SCRIPT="{{.TASKFILE_DIR}}/../src/tasks/markdown/lint-fix.ts"
70
+
71
+ if [ "$REPO_URL" = "https://github.com/northbridge-security/ai-toolkit" ] && [ -f "$SCRIPT" ]; then
72
+ bun run "$SCRIPT"
73
+ else
74
+ # Fallback to ai-toolkit CLI
75
+ npx @northbridge-security/ai-toolkit markdown lint --fix -f "$FILES"
76
+ fi
77
+ env:
78
+ FILES: "{{.FILE_PATTERNS}}"
79
+ VERBOSE: "{{.VERBOSE_FLAG}}"
80
+
81
+ setup:
82
+ desc: "Install markdownlint CLI tool and create .markdownlint.yaml config"
83
+ aliases: [s]
84
+ silent: true
85
+ cmds:
86
+ - |
87
+ REPO_URL=$(task git:repo:url 2>/dev/null || echo "")
88
+ SCRIPT="{{.TASKFILE_DIR}}/../src/tasks/markdown/setup.ts"
89
+
90
+ if [ "$REPO_URL" = "https://github.com/northbridge-security/ai-toolkit" ] && [ -f "$SCRIPT" ]; then
91
+ bun run "$SCRIPT"
92
+ else
93
+ # Fallback to ai-toolkit CLI
94
+ npx @northbridge-security/ai-toolkit markdown setup
95
+ fi
@@ -0,0 +1,350 @@
1
+ version: "3"
2
+
3
+ # 1Password Secret Management Tasks
4
+ # Minimal set of tasks for secure secret management
5
+
6
+ tasks:
7
+ default:
8
+ desc: "Show available 1Password tasks"
9
+ aliases: [help]
10
+ silent: true
11
+ cmds:
12
+ - |
13
+ # Color codes
14
+ GREEN='\033[0;32m'
15
+ YELLOW='\033[0;33m'
16
+ RED='\033[0;31m'
17
+ BOLD='\033[1m'
18
+ NC='\033[0m'
19
+
20
+ echo -e "${BOLD}1Password Secret Management${NC}"
21
+ echo ""
22
+ echo -e "${YELLOW}ℹ️ Secrets loaded automatically by tasks that need them${NC}"
23
+ echo ""
24
+ echo "Command Alias Description Examples"
25
+ echo "───────────────────────────────────────────────────────────────────────────────────────────────────"
26
+ echo -e " ${GREEN}source \$(task op:export)${NC} ${YELLOW}op:x${NC} Load secrets into shell (interactive)"
27
+ echo -e " ${GREEN}source \$(task op:export:force)${NC} ${YELLOW}op:xf${NC} Force reload all secrets"
28
+ echo -e " ${GREEN}task op:verify${NC} ${YELLOW}op:ve${NC} Verify required secrets are loaded"
29
+ echo -e " ${GREEN}task op:validate${NC} ${YELLOW}op:v${NC} Validate all exported secrets"
30
+ echo -e " ${GREEN}task op:cleanup${NC} ${YELLOW}op:c${NC} Clean up temp secret files"
31
+ echo -e " ${GREEN}task op:test${NC} ${YELLOW}op:t${NC} Test GitHub token permissions"
32
+
33
+ export:
34
+ desc: "Export secrets to temp file - Use: source $(task op:export)"
35
+ aliases: [x]
36
+ silent: true
37
+ cmds:
38
+ - |
39
+ set -euo pipefail
40
+
41
+ # Get unique temp directory for this repo
42
+ REPO_PATH=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
43
+ REPO_HASH=$(echo "$REPO_PATH" | shasum -a 256 | cut -d' ' -f1 | cut -c1-12)
44
+ TEMP_DIR="/tmp/op-secrets-$REPO_HASH"
45
+ TEMP_ENV="$TEMP_DIR/.env"
46
+
47
+ # Check if already exported (idempotent)
48
+ if [ -f "$TEMP_ENV" ]; then
49
+ # Verify file is recent (< 1 hour old)
50
+ if [ "$(uname)" = "Darwin" ]; then
51
+ FILE_AGE=$(stat -f %m "$TEMP_ENV" 2>/dev/null || echo 0)
52
+ else
53
+ FILE_AGE=$(stat -c %Y "$TEMP_ENV" 2>/dev/null || echo 0)
54
+ fi
55
+ CURRENT_TIME=$(date +%s)
56
+ AGE_SECONDS=$((CURRENT_TIME - FILE_AGE))
57
+
58
+ if [ $AGE_SECONDS -lt 3600 ]; then
59
+ # File is fresh, reuse it
60
+ echo "$TEMP_ENV"
61
+ exit 0
62
+ fi
63
+ fi
64
+
65
+ # Check if 1Password CLI is available
66
+ OP_AVAILABLE=false
67
+ if command -v op &> /dev/null; then
68
+ OP_AVAILABLE=true
69
+ fi
70
+
71
+ # Create secure temp directory
72
+ mkdir -p "$TEMP_DIR"
73
+ chmod 700 "$TEMP_DIR"
74
+
75
+ # Create temp file with secure permissions
76
+ touch "$TEMP_ENV"
77
+ chmod 600 "$TEMP_ENV"
78
+
79
+ # Clear file
80
+ : > "$TEMP_ENV"
81
+
82
+ # Track unresolved op:// references
83
+ UNRESOLVED_REFS=""
84
+
85
+ # Function to process an env file
86
+ process_env_file() {
87
+ local env_file="$1"
88
+ [ -f "$env_file" ] || return 0
89
+
90
+ while IFS='=' read -r key value || [ -n "$key" ]; do
91
+ # Skip comments and empty lines
92
+ [[ "$key" =~ ^#.*$ ]] || [[ -z "$key" ]] && continue
93
+
94
+ # Remove any existing entry for this key (allows override)
95
+ if [ -f "$TEMP_ENV" ]; then
96
+ grep -v "^export $key=" "$TEMP_ENV" > "$TEMP_ENV.tmp" 2>/dev/null || true
97
+ mv "$TEMP_ENV.tmp" "$TEMP_ENV" 2>/dev/null || true
98
+ fi
99
+
100
+ # Resolve op:// references via 1Password CLI
101
+ if [[ "$value" =~ ^op:// ]]; then
102
+ if [ "$OP_AVAILABLE" = true ]; then
103
+ resolved=$(op read "$value" 2>/dev/null) || true
104
+ if [ -n "$resolved" ]; then
105
+ echo "export $key='$resolved'" >> "$TEMP_ENV"
106
+ else
107
+ # op available but resolution failed - track for error
108
+ UNRESOLVED_REFS="$UNRESOLVED_REFS\n $key=$value"
109
+ fi
110
+ else
111
+ # op not available - track unresolved reference
112
+ UNRESOLVED_REFS="$UNRESOLVED_REFS\n $key=$value"
113
+ fi
114
+ else
115
+ # Plain text value, export as-is
116
+ echo "export $key='$value'" >> "$TEMP_ENV"
117
+ fi
118
+ done < "$env_file"
119
+ }
120
+
121
+ # Process .env first, then .env.local (local overrides base)
122
+ process_env_file ".env"
123
+ process_env_file ".env.local"
124
+
125
+ # Only error if there are unresolved op:// references
126
+ if [ -n "$UNRESOLVED_REFS" ]; then
127
+ if [ "$OP_AVAILABLE" = true ]; then
128
+ echo "❌ Failed to resolve 1Password references:" >&2
129
+ else
130
+ echo "❌ 1Password CLI (op) not installed but op:// references found:" >&2
131
+ fi
132
+ echo -e "$UNRESOLVED_REFS" >&2
133
+ echo "" >&2
134
+ if [ "$OP_AVAILABLE" = false ]; then
135
+ echo "Install 1Password CLI: https://developer.1password.com/docs/cli/get-started/" >&2
136
+ echo "Or replace op:// references with plain values in .env.local" >&2
137
+ else
138
+ echo "Ensure 1Password is unlocked and references are valid" >&2
139
+ fi
140
+ exit 1
141
+ fi
142
+
143
+ # Output temp file path (for sourcing)
144
+ echo "$TEMP_ENV"
145
+
146
+ # Security: Auto-delete secrets file after 10 seconds
147
+ # This runs in background so the task returns immediately
148
+ # The file will be deleted even if the parent shell exits
149
+ (sleep 10 && rm -f "$TEMP_ENV" 2>/dev/null) &
150
+ disown 2>/dev/null || true
151
+
152
+ export:force:
153
+ desc: "Force re-export secrets - Use: source $(task op:export:force)"
154
+ aliases: [xf]
155
+ silent: true
156
+ cmds:
157
+ - |
158
+ # Delete existing temp file to force re-export
159
+ REPO_PATH=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
160
+ REPO_HASH=$(echo "$REPO_PATH" | shasum -a 256 | cut -d' ' -f1 | cut -c1-12)
161
+ rm -f "/tmp/op-secrets-$REPO_HASH/.env"
162
+
163
+ # Run normal export
164
+ task op:export
165
+
166
+ verify:
167
+ desc: "Verify required secrets are loaded (at least one AI key + required tokens)"
168
+ aliases: [ve]
169
+ silent: true
170
+ cmds:
171
+ - |
172
+ set -euo pipefail
173
+
174
+ # Color codes
175
+ RED='\033[0;31m'
176
+ GREEN='\033[0;32m'
177
+ NC='\033[0m'
178
+
179
+ failed=false
180
+
181
+ # Check at least one AI API key is set and resolved
182
+ ai_key_found=false
183
+ for key in ANTHROPIC_API_KEY PERPLEXITY_API_KEY OPENAI_API_KEY; do
184
+ value="${!key:-}"
185
+ if [ -n "$value" ] && [[ ! "$value" =~ ^op:// ]]; then
186
+ ai_key_found=true
187
+ break
188
+ fi
189
+ done
190
+
191
+ if [ "$ai_key_found" = false ]; then
192
+ echo -e "${RED}❌ No AI API key found${NC}" >&2
193
+ echo " Required: At least one of ANTHROPIC_API_KEY, PERPLEXITY_API_KEY, or OPENAI_API_KEY" >&2
194
+ echo " Run: source \$(task op:export)" >&2
195
+ failed=true
196
+ fi
197
+
198
+ # Check required tokens
199
+ for key in GITHUB_TOKEN SEMGREP_APP_TOKEN; do
200
+ value="${!key:-}"
201
+
202
+ if [ -z "$value" ]; then
203
+ echo -e "${RED}❌ $key: NOT SET${NC}" >&2
204
+ failed=true
205
+ continue
206
+ fi
207
+
208
+ if [[ "$value" =~ ^op:// ]]; then
209
+ echo -e "${RED}❌ $key: NOT RESOLVED${NC}" >&2
210
+ echo " Run: source \$(task op:export)" >&2
211
+ failed=true
212
+ fi
213
+ done
214
+
215
+ if [ "$failed" = true ]; then
216
+ exit 1
217
+ fi
218
+
219
+ cleanup:
220
+ desc: "Clean up exported secrets temp file"
221
+ aliases: [c]
222
+ silent: true
223
+ cmds:
224
+ - |
225
+ REPO_PATH=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
226
+ REPO_HASH=$(echo "$REPO_PATH" | shasum -a 256 | cut -d' ' -f1 | cut -c1-12)
227
+ TEMP_DIR="/tmp/op-secrets-$REPO_HASH"
228
+
229
+ if [ -d "$TEMP_DIR" ]; then
230
+ rm -rf "$TEMP_DIR"
231
+ echo "✓ Cleaned up secrets temp file"
232
+ else
233
+ echo "No temp files to clean"
234
+ fi
235
+
236
+ validate:
237
+ desc: "Validate exported environment variables (idempotent, silent if valid)"
238
+ aliases: [v]
239
+ silent: true
240
+ cmds:
241
+ - |
242
+ # Read expected variables from .env and .env.local (combined, deduplicated)
243
+ expected_vars=$(cat .env .env.local 2>/dev/null | grep -E "^[A-Z_]+=" | cut -d= -f1 | sort -u)
244
+
245
+ if [ -z "$expected_vars" ]; then
246
+ echo "❌ No .env file found or no variables defined" >&2
247
+ exit 1
248
+ fi
249
+
250
+ # Track failures
251
+ failed=false
252
+
253
+ # Check each variable
254
+ for var in $expected_vars; do
255
+ value="${!var}"
256
+
257
+ # Check if variable is set
258
+ if [ -z "$value" ]; then
259
+ echo "❌ $var: NOT SET" >&2
260
+ failed=true
261
+ continue
262
+ fi
263
+
264
+ # Check if still in op:// format (not exported)
265
+ if [[ "$value" =~ ^op:// ]]; then
266
+ echo "❌ $var: NOT RESOLVED (run: source \$(task op:export))" >&2
267
+ failed=true
268
+ continue
269
+ fi
270
+ done
271
+
272
+ # Only exit with error if validation failed
273
+ if [ "$failed" = true ]; then
274
+ exit 1
275
+ fi
276
+
277
+ test:
278
+ desc: "Test GitHub token permissions using .env mapping"
279
+ aliases: [t]
280
+ silent: true
281
+ cmds:
282
+ - |
283
+ echo "GitHub Token Permission Test"
284
+ echo "============================"
285
+ echo ""
286
+
287
+ # Check gh CLI is installed
288
+ if ! command -v gh &> /dev/null; then
289
+ echo "❌ GitHub CLI not found. Install: brew install gh" >&2
290
+ exit 1
291
+ fi
292
+
293
+ # Get GITHUB_TOKEN reference from .env
294
+ github_token_ref=$(grep "^GITHUB_TOKEN=" .env | cut -d= -f2)
295
+ if [ -z "$github_token_ref" ]; then
296
+ echo "❌ GITHUB_TOKEN not found in .env" >&2
297
+ exit 1
298
+ fi
299
+
300
+ # Resolve from 1Password using .env mapping
301
+ if [[ "$github_token_ref" =~ ^op:// ]]; then
302
+ export GITHUB_TOKEN=$(op read "$github_token_ref" 2>/dev/null)
303
+ if [ $? -ne 0 ]; then
304
+ echo "❌ Could not resolve GITHUB_TOKEN from 1Password" >&2
305
+ echo "Hint: Ensure 1Password is unlocked" >&2
306
+ exit 1
307
+ fi
308
+ else
309
+ export GITHUB_TOKEN="$github_token_ref"
310
+ fi
311
+
312
+ export GH_TOKEN="$GITHUB_TOKEN"
313
+ echo "Token loaded: ${GITHUB_TOKEN:0:10}..."
314
+ echo ""
315
+
316
+ # Get repository from git remote
317
+ REPO=$(git config --get remote.origin.url | sed -E "s|^.*[:/]([^/]+/[^/]+)(.git)?$|\1|" | sed "s/\.git$//")
318
+ echo "Testing: $REPO"
319
+ echo ""
320
+
321
+ # Test read permissions
322
+ echo "Testing read permissions..."
323
+ gh repo view "$REPO" --json name > /dev/null 2>&1 && echo " ✅ Read repository" || { echo " ❌ Read repository" >&2; exit 1; }
324
+ gh issue list --repo "$REPO" --limit 1 > /dev/null 2>&1 && echo " ✅ Read issues" || echo " ⚠️ Read issues"
325
+ gh pr list --repo "$REPO" --limit 1 > /dev/null 2>&1 && echo " ✅ Read PRs" || echo " ⚠️ Read PRs"
326
+ gh run list --repo "$REPO" --limit 1 > /dev/null 2>&1 && echo " ✅ Read workflows" || echo " ⚠️ Read workflows"
327
+ echo ""
328
+
329
+ # Test write restrictions (should fail)
330
+ echo "Testing write restrictions..."
331
+ ! gh secret list --repo "$REPO" > /dev/null 2>&1 && echo " ✅ Cannot read secrets" || { echo " ❌ SECURITY: Can read secrets!" >&2; exit 1; }
332
+
333
+ TEMP_FILE="temp-test-$(date +%s).md"
334
+ if echo "test" | gh api "repos/$REPO/contents/$TEMP_FILE" --method PUT --field message="test" --field content="dGVzdA==" --silent > /dev/null 2>&1; then
335
+ echo " ❌ SECURITY: Can write files!" >&2
336
+ gh api "repos/$REPO/contents/$TEMP_FILE" --method DELETE --field message="cleanup" --field sha="$(gh api "repos/$REPO/contents/$TEMP_FILE" --jq .sha)" --silent 2>&1 || true
337
+ exit 1
338
+ else
339
+ echo " ✅ Cannot write files"
340
+ fi
341
+
342
+ WORKFLOW=$(gh api "repos/$REPO/actions/workflows" --jq ".workflows[0].path" 2>/dev/null)
343
+ if [ -n "$WORKFLOW" ]; then
344
+ ! gh workflow run "$WORKFLOW" --repo "$REPO" > /dev/null 2>&1 && echo " ✅ Cannot trigger workflows" || { echo " ❌ SECURITY: Can trigger workflows!" >&2; exit 1; }
345
+ else
346
+ echo " ⚠️ No workflows to test"
347
+ fi
348
+
349
+ echo ""
350
+ echo "✅ All tests passed - token follows least privilege"