@elnora-ai/linear 1.0.1 → 2.0.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/.claude-plugin/marketplace.json +7 -2
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +25 -1
- package/README.md +275 -25
- package/agents/linear-issue-creator.md +135 -17
- package/agents/linear-issue-reviewer.md +122 -23
- package/agents/linear-issue-updater.md +137 -25
- package/agents/linear-state-curator.md +173 -0
- package/agents/linear-url-to-issues.md +190 -26
- package/commands/linear-cleanup.md +64 -29
- package/dist/cli.js +69 -1
- package/dist/cli.js.map +1 -1
- package/dist/client/auth.d.ts +10 -0
- package/dist/client/auth.d.ts.map +1 -1
- package/dist/client/auth.js +50 -3
- package/dist/client/auth.js.map +1 -1
- package/dist/client/linear-client.d.ts +7 -0
- package/dist/client/linear-client.d.ts.map +1 -1
- package/dist/client/linear-client.js +13 -1
- package/dist/client/linear-client.js.map +1 -1
- package/dist/commands/agent-activities.d.ts +3 -0
- package/dist/commands/agent-activities.d.ts.map +1 -0
- package/dist/commands/agent-activities.js +144 -0
- package/dist/commands/agent-activities.js.map +1 -0
- package/dist/commands/agent-sessions.d.ts +3 -0
- package/dist/commands/agent-sessions.d.ts.map +1 -0
- package/dist/commands/agent-sessions.js +132 -0
- package/dist/commands/agent-sessions.js.map +1 -0
- package/dist/commands/attachments.d.ts +3 -0
- package/dist/commands/attachments.d.ts.map +1 -0
- package/dist/commands/attachments.js +265 -0
- package/dist/commands/attachments.js.map +1 -0
- package/dist/commands/audit.d.ts +3 -0
- package/dist/commands/audit.d.ts.map +1 -0
- package/dist/commands/audit.js +73 -0
- package/dist/commands/audit.js.map +1 -0
- package/dist/commands/comments.d.ts +3 -0
- package/dist/commands/comments.d.ts.map +1 -0
- package/dist/commands/comments.js +107 -0
- package/dist/commands/comments.js.map +1 -0
- package/dist/commands/completion.d.ts +3 -0
- package/dist/commands/completion.d.ts.map +1 -0
- package/dist/commands/completion.js +62 -0
- package/dist/commands/completion.js.map +1 -0
- package/dist/commands/context.d.ts +3 -0
- package/dist/commands/context.d.ts.map +1 -0
- package/dist/commands/context.js +94 -0
- package/dist/commands/context.js.map +1 -0
- package/dist/commands/curator.d.ts +14 -0
- package/dist/commands/curator.d.ts.map +1 -1
- package/dist/commands/curator.js +97 -19
- package/dist/commands/curator.js.map +1 -1
- package/dist/commands/customer-needs.d.ts +3 -0
- package/dist/commands/customer-needs.d.ts.map +1 -0
- package/dist/commands/customer-needs.js +198 -0
- package/dist/commands/customer-needs.js.map +1 -0
- package/dist/commands/customers.d.ts +5 -0
- package/dist/commands/customers.d.ts.map +1 -0
- package/dist/commands/customers.js +201 -0
- package/dist/commands/customers.js.map +1 -0
- package/dist/commands/cycles.d.ts +3 -0
- package/dist/commands/cycles.d.ts.map +1 -0
- package/dist/commands/cycles.js +67 -0
- package/dist/commands/cycles.js.map +1 -0
- package/dist/commands/documents.d.ts +3 -0
- package/dist/commands/documents.d.ts.map +1 -0
- package/dist/commands/documents.js +105 -0
- package/dist/commands/documents.js.map +1 -0
- package/dist/commands/favorites.d.ts +3 -0
- package/dist/commands/favorites.d.ts.map +1 -0
- package/dist/commands/favorites.js +101 -0
- package/dist/commands/favorites.js.map +1 -0
- package/dist/commands/index.d.ts +30 -0
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +30 -0
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/initiatives.d.ts +3 -0
- package/dist/commands/initiatives.d.ts.map +1 -0
- package/dist/commands/initiatives.js +106 -0
- package/dist/commands/initiatives.js.map +1 -0
- package/dist/commands/issues.d.ts +21 -0
- package/dist/commands/issues.d.ts.map +1 -0
- package/dist/commands/issues.js +1083 -0
- package/dist/commands/issues.js.map +1 -0
- package/dist/commands/labels.d.ts +3 -0
- package/dist/commands/labels.d.ts.map +1 -0
- package/dist/commands/labels.js +111 -0
- package/dist/commands/labels.js.map +1 -0
- package/dist/commands/milestones.d.ts +3 -0
- package/dist/commands/milestones.d.ts.map +1 -0
- package/dist/commands/milestones.js +94 -0
- package/dist/commands/milestones.js.map +1 -0
- package/dist/commands/notifications.d.ts +3 -0
- package/dist/commands/notifications.d.ts.map +1 -0
- package/dist/commands/notifications.js +130 -0
- package/dist/commands/notifications.js.map +1 -0
- package/dist/commands/project-labels.d.ts +3 -0
- package/dist/commands/project-labels.d.ts.map +1 -0
- package/dist/commands/project-labels.js +80 -0
- package/dist/commands/project-labels.js.map +1 -0
- package/dist/commands/project-relations.d.ts +3 -0
- package/dist/commands/project-relations.d.ts.map +1 -0
- package/dist/commands/project-relations.js +96 -0
- package/dist/commands/project-relations.js.map +1 -0
- package/dist/commands/projects.d.ts +3 -0
- package/dist/commands/projects.d.ts.map +1 -0
- package/dist/commands/projects.js +263 -0
- package/dist/commands/projects.js.map +1 -0
- package/dist/commands/quota.d.ts +3 -0
- package/dist/commands/quota.d.ts.map +1 -0
- package/dist/commands/quota.js +28 -0
- package/dist/commands/quota.js.map +1 -0
- package/dist/commands/reactions.d.ts +7 -0
- package/dist/commands/reactions.d.ts.map +1 -0
- package/dist/commands/reactions.js +53 -0
- package/dist/commands/reactions.js.map +1 -0
- package/dist/commands/relations.d.ts +3 -0
- package/dist/commands/relations.d.ts.map +1 -0
- package/dist/commands/relations.js +73 -0
- package/dist/commands/relations.js.map +1 -0
- package/dist/commands/states.d.ts +3 -0
- package/dist/commands/states.d.ts.map +1 -0
- package/dist/commands/states.js +52 -0
- package/dist/commands/states.js.map +1 -0
- package/dist/commands/status-updates.d.ts +3 -0
- package/dist/commands/status-updates.d.ts.map +1 -0
- package/dist/commands/status-updates.js +117 -0
- package/dist/commands/status-updates.js.map +1 -0
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +58 -18
- package/dist/commands/sync.js.map +1 -1
- package/dist/commands/teams.d.ts +3 -0
- package/dist/commands/teams.d.ts.map +1 -0
- package/dist/commands/teams.js +135 -0
- package/dist/commands/teams.js.map +1 -0
- package/dist/commands/templates.d.ts +3 -0
- package/dist/commands/templates.d.ts.map +1 -0
- package/dist/commands/templates.js +76 -0
- package/dist/commands/templates.js.map +1 -0
- package/dist/commands/users.d.ts +3 -0
- package/dist/commands/users.d.ts.map +1 -0
- package/dist/commands/users.js +40 -0
- package/dist/commands/users.js.map +1 -0
- package/dist/commands/views.d.ts +3 -0
- package/dist/commands/views.d.ts.map +1 -0
- package/dist/commands/views.js +177 -0
- package/dist/commands/views.js.map +1 -0
- package/dist/commands/webhooks.d.ts +3 -0
- package/dist/commands/webhooks.d.ts.map +1 -0
- package/dist/commands/webhooks.js +234 -0
- package/dist/commands/webhooks.js.map +1 -0
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/loader.js +3 -0
- package/dist/config/loader.js.map +1 -1
- package/dist/config/types.d.ts +15 -1
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js +1 -0
- package/dist/config/types.js.map +1 -1
- package/dist/curator/dispatch.d.ts +52 -0
- package/dist/curator/dispatch.d.ts.map +1 -0
- package/dist/curator/dispatch.js +144 -0
- package/dist/curator/dispatch.js.map +1 -0
- package/dist/curator/index.d.ts +5 -0
- package/dist/curator/index.d.ts.map +1 -0
- package/dist/curator/index.js +5 -0
- package/dist/curator/index.js.map +1 -0
- package/dist/curator/llm.d.ts +70 -0
- package/dist/curator/llm.d.ts.map +1 -0
- package/dist/curator/llm.js +107 -0
- package/dist/curator/llm.js.map +1 -0
- package/dist/curator/snapshot.d.ts +34 -0
- package/dist/curator/snapshot.d.ts.map +1 -0
- package/dist/curator/snapshot.js +127 -0
- package/dist/curator/snapshot.js.map +1 -0
- package/dist/curator/state.d.ts +50 -0
- package/dist/curator/state.d.ts.map +1 -0
- package/dist/curator/state.js +125 -0
- package/dist/curator/state.js.map +1 -0
- package/dist/lib/bulk-graphql.d.ts +144 -0
- package/dist/lib/bulk-graphql.d.ts.map +1 -0
- package/dist/lib/bulk-graphql.js +380 -0
- package/dist/lib/bulk-graphql.js.map +1 -0
- package/dist/lib/index.d.ts +2 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +2 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/output/cli.d.ts +17 -0
- package/dist/output/cli.d.ts.map +1 -0
- package/dist/output/cli.js +252 -0
- package/dist/output/cli.js.map +1 -0
- package/dist/output/formatter.d.ts +6 -0
- package/dist/output/formatter.d.ts.map +1 -1
- package/dist/output/formatter.js +10 -0
- package/dist/output/formatter.js.map +1 -1
- package/dist/output/index.d.ts +1 -0
- package/dist/output/index.d.ts.map +1 -1
- package/dist/output/index.js +1 -0
- package/dist/output/index.js.map +1 -1
- package/dist/scripts/sync-linear-templates.d.ts +26 -0
- package/dist/scripts/sync-linear-templates.d.ts.map +1 -0
- package/dist/scripts/sync-linear-templates.js +115 -0
- package/dist/scripts/sync-linear-templates.js.map +1 -0
- package/dist/signals/github-commits.d.ts +31 -0
- package/dist/signals/github-commits.d.ts.map +1 -0
- package/dist/signals/github-commits.js +127 -0
- package/dist/signals/github-commits.js.map +1 -0
- package/dist/signals/github-pr.d.ts +16 -0
- package/dist/signals/github-pr.d.ts.map +1 -0
- package/dist/signals/github-pr.js +98 -0
- package/dist/signals/github-pr.js.map +1 -0
- package/dist/signals/index.d.ts +4 -0
- package/dist/signals/index.d.ts.map +1 -1
- package/dist/signals/index.js +4 -0
- package/dist/signals/index.js.map +1 -1
- package/dist/signals/linear-issues.d.ts +20 -0
- package/dist/signals/linear-issues.d.ts.map +1 -0
- package/dist/signals/linear-issues.js +115 -0
- package/dist/signals/linear-issues.js.map +1 -0
- package/dist/signals/registry.d.ts +4 -3
- package/dist/signals/registry.d.ts.map +1 -1
- package/dist/signals/registry.js +33 -11
- package/dist/signals/registry.js.map +1 -1
- package/dist/signals/slack-messages.d.ts +20 -0
- package/dist/signals/slack-messages.d.ts.map +1 -0
- package/dist/signals/slack-messages.js +129 -0
- package/dist/signals/slack-messages.js.map +1 -0
- package/dist/utils/errors.d.ts +81 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +110 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/index.d.ts +9 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +9 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/label-policy.d.ts +60 -0
- package/dist/utils/label-policy.d.ts.map +1 -0
- package/dist/utils/label-policy.js +103 -0
- package/dist/utils/label-policy.js.map +1 -0
- package/dist/utils/parse.d.ts +48 -0
- package/dist/utils/parse.d.ts.map +1 -0
- package/dist/utils/parse.js +133 -0
- package/dist/utils/parse.js.map +1 -0
- package/dist/utils/project-status.d.ts +6 -0
- package/dist/utils/project-status.d.ts.map +1 -0
- package/dist/utils/project-status.js +33 -0
- package/dist/utils/project-status.js.map +1 -0
- package/dist/utils/rate-limit.d.ts +24 -0
- package/dist/utils/rate-limit.d.ts.map +1 -0
- package/dist/utils/rate-limit.js +89 -0
- package/dist/utils/rate-limit.js.map +1 -0
- package/dist/utils/resolve.d.ts +84 -0
- package/dist/utils/resolve.d.ts.map +1 -0
- package/dist/utils/resolve.js +172 -0
- package/dist/utils/resolve.js.map +1 -0
- package/dist/utils/sleep.d.ts +2 -0
- package/dist/utils/sleep.d.ts.map +1 -0
- package/dist/utils/sleep.js +4 -0
- package/dist/utils/sleep.js.map +1 -0
- package/dist/utils/webhook-verify.d.ts +42 -0
- package/dist/utils/webhook-verify.d.ts.map +1 -0
- package/dist/utils/webhook-verify.js +65 -0
- package/dist/utils/webhook-verify.js.map +1 -0
- package/package.json +7 -2
- package/references/agent-description-template.md +31 -0
- package/references/cli-reference.md +227 -0
- package/references/curator-tiering-rules.md +78 -0
- package/references/label-policy.example.json +37 -0
- package/references/label-policy.placeholder.json +6 -0
- package/references/settings-template.md +30 -0
- package/references/signal-sources.example.json +0 -8
- package/references/sla-reference.md +70 -0
- package/references/template-index.md +34 -0
- package/references/workspace-labels.md +124 -0
- package/references/workspace-projects.md +56 -0
- package/references/workspace-routing.md +58 -0
- package/schemas/label-policy.json +72 -0
- package/scripts/postinstall.mjs +195 -0
- package/skills/linear-workspace/SKILL.md +65 -4
- package/templates/ACC-PRO-provision.md +74 -0
- package/templates/ACC-PRV-privileged.md +66 -0
- package/templates/ACC-QTR-review.md +77 -0
- package/templates/ACC-REV-revoke.md +67 -0
- package/templates/AI-USE-capability.md +111 -0
- package/templates/AUD-CAP-corrective.md +89 -0
- package/templates/AUD-INT-internal.md +92 -0
- package/templates/AUD-MGT-management.md +110 -0
- package/templates/CHG-MAJ-major.md +110 -0
- package/templates/CHG-SIG-significant.md +83 -0
- package/templates/CHG-STD-standard.md +47 -0
- package/templates/LRN-DOC-lessons.md +75 -0
- package/templates/OPS-BCK-backup.md +99 -0
- package/templates/OPS-DAT-data-mod.md +98 -0
- package/templates/RCA-DOC-root-cause.md +105 -0
- package/templates/RSK-ASS-assessment.md +87 -0
- package/templates/RSK-VND-vendor.md +113 -0
- package/templates/SEC-INC-incident.md +76 -0
- package/templates/SEC-PEN-pentest.md +58 -0
- package/templates/SEC-VLN-vulnerability.md +69 -0
- package/templates/SLA-AVL-availability.md +86 -0
- package/templates/SLA-OPS-operational.md +70 -0
- package/templates/agent-server-template/README.md +88 -0
- package/templates/agent-server-template/server.example.ts +185 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Workspace Projects — Documentation Template
|
|
2
|
+
|
|
3
|
+
A schema you can fill in to document your projects per team. Pair this with `projects.json` (the machine-readable copy that the CLI consumes via `sync` and `context`).
|
|
4
|
+
|
|
5
|
+
Load this file when you need full project context that doesn't fit on a `context --team` summary. Agents normally do not read it.
|
|
6
|
+
|
|
7
|
+
## Projects by Team and Status
|
|
8
|
+
|
|
9
|
+
### `<Team-1>`
|
|
10
|
+
|
|
11
|
+
#### In Progress
|
|
12
|
+
| Project | Priority | Lead | Purpose |
|
|
13
|
+
|---------|----------|------|---------|
|
|
14
|
+
| `<Project name>` | `<Urgent|High|Normal|Low>` | `<lead>` | `<one-line purpose>` |
|
|
15
|
+
|
|
16
|
+
#### Planned
|
|
17
|
+
| Project | Priority | Lead | Purpose |
|
|
18
|
+
|---------|----------|------|---------|
|
|
19
|
+
|
|
20
|
+
#### Backlog
|
|
21
|
+
| Project | Priority | Lead | Purpose |
|
|
22
|
+
|---------|----------|------|---------|
|
|
23
|
+
|
|
24
|
+
#### Completed
|
|
25
|
+
| Project | Priority | Lead | Purpose |
|
|
26
|
+
|---------|----------|------|---------|
|
|
27
|
+
|
|
28
|
+
#### Canceled
|
|
29
|
+
| Project | Priority | Lead | Purpose |
|
|
30
|
+
|---------|----------|------|---------|
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
### `<Team-2>`
|
|
35
|
+
|
|
36
|
+
(same structure)
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Compliance workflow projects
|
|
41
|
+
|
|
42
|
+
If you use the bundled compliance templates (see `template-index.md`), each template usually maps to its own project so the audit trail is easy to find. Typical names:
|
|
43
|
+
|
|
44
|
+
- User Onboarding / Offboarding
|
|
45
|
+
- Access Provisioning / Revocation / Reviews / Privileged Access
|
|
46
|
+
- Standard / Significant / Major Changes
|
|
47
|
+
- Security Incidents / Vulnerability Management / Pentest Remediation
|
|
48
|
+
- Availability Incidents / Operational Requests
|
|
49
|
+
- Root Cause Analysis / Lessons Learned / Corrective Actions
|
|
50
|
+
- Internal Audits / Management Reviews
|
|
51
|
+
- Risk Assessments / Vendor Assessments
|
|
52
|
+
- AI Governance / Backup & DR Testing / Data Modifications
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
*Routing keywords: `workspace-routing.md` | Labels: `workspace-labels.md` | Run `elnora-linear sync all` to refresh the JSON references from Linear.*
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Workspace Routing
|
|
2
|
+
|
|
3
|
+
Schema/template for documenting how your workspace's teams + projects + labels map to your work intake. Replace the examples below with your own workspace structure; populate `teams.json`, `projects.json`, and `label-policy.json` with the underlying machine-readable data.
|
|
4
|
+
|
|
5
|
+
## Teams (example)
|
|
6
|
+
|
|
7
|
+
| Team | Prefix | Use For |
|
|
8
|
+
|------|--------|---------|
|
|
9
|
+
| **Engineering** | ENG- | Customer-facing product code, features, bugs |
|
|
10
|
+
| **Operations** | OPS- | Internal: tooling, compliance docs, HR, access management |
|
|
11
|
+
| **Security** | SEC- | CVE/vulnerability remediation, pentest findings, incidents (not security features) |
|
|
12
|
+
| **Customer Success** | CUS- | Customer support, onboarding, client feedback |
|
|
13
|
+
|
|
14
|
+
## Routing Keywords (example)
|
|
15
|
+
|
|
16
|
+
| Keywords | Route To |
|
|
17
|
+
|----------|----------|
|
|
18
|
+
| feature, bug, build, implement, develop, code, product, ship, api, ui | **Engineering** |
|
|
19
|
+
| vulnerability, CVE, CodeQL, dependabot, pentest finding, patch, security incident | **Security** |
|
|
20
|
+
| internal tooling, internal infrastructure, dev environment, plugin, marketplace, cli setup | **Operations** |
|
|
21
|
+
| document, record, audit, review completed, change approved, compliance | **Operations** |
|
|
22
|
+
| onboarding, offboarding, access provision, access revoke, quarterly review | **Operations** |
|
|
23
|
+
| change request, policy change, procedure change, ISMS change | **Operations** |
|
|
24
|
+
| internal audit, management review, corrective action, risk assessment | **Operations** |
|
|
25
|
+
| AI use case, AI capability scope, model family change, foundation model swap, AI governance | **Operations** |
|
|
26
|
+
| hr, admin, process improvement, team operations, company operations | **Operations** |
|
|
27
|
+
| customer, support request, user reported, client feedback, customer onboarding | **Customer Success** |
|
|
28
|
+
|
|
29
|
+
**Default:** Engineering
|
|
30
|
+
|
|
31
|
+
## Project Keywords (schema)
|
|
32
|
+
|
|
33
|
+
Each project belongs to a specific team. Document yours in `workspace-projects.md` and keep the underlying mapping in `projects.json`.
|
|
34
|
+
|
|
35
|
+
| Project | Keywords | Team |
|
|
36
|
+
|---------|----------|------|
|
|
37
|
+
| `<Project name>` | `<keyword1>, <keyword2>, ...` | `<team>` |
|
|
38
|
+
|
|
39
|
+
## State Mapping (example)
|
|
40
|
+
|
|
41
|
+
| Project Status | Issue State |
|
|
42
|
+
|----------------|-------------|
|
|
43
|
+
| In Progress | Todo |
|
|
44
|
+
| Planned | Todo |
|
|
45
|
+
| Backlog | Backlog |
|
|
46
|
+
|
|
47
|
+
(see `recommendedStateForStatus` in the CLI; this table is the human-readable version of that logic.)
|
|
48
|
+
|
|
49
|
+
## Assignees
|
|
50
|
+
|
|
51
|
+
Document your team's assignment rules here. Common patterns:
|
|
52
|
+
|
|
53
|
+
- Map roles to default assignees (e.g. "platform code → Platform lead").
|
|
54
|
+
- Rule of thumb: ASK the user for an assignee if not specified — defaults can silently route to the wrong person.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
*Projects: `workspace-projects.md` | Labels: `workspace-labels.md` | Run `elnora-linear sync all` to refresh JSON references from Linear.*
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://github.com/Elnora-AI/elnora-linear/blob/main/schemas/label-policy.json",
|
|
4
|
+
"title": "Label Policy",
|
|
5
|
+
"description": "Per-team required-label rules. Read by `issues create`, `issues update`, and `context` to surface required labels + enforce them at write time. Keyed by team key.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"properties": {
|
|
9
|
+
"$schema": { "type": "string" },
|
|
10
|
+
"_placeholder": { "type": "boolean", "const": true },
|
|
11
|
+
"_example": { "type": "boolean", "const": true },
|
|
12
|
+
"_populated_by": { "type": "string" },
|
|
13
|
+
"policies": {
|
|
14
|
+
"type": "object",
|
|
15
|
+
"description": "Map of team key → policy. Keys are uppercase Linear team keys (e.g. ENG).",
|
|
16
|
+
"patternProperties": {
|
|
17
|
+
"^[A-Z][A-Z0-9]*$": {
|
|
18
|
+
"type": "object",
|
|
19
|
+
"additionalProperties": false,
|
|
20
|
+
"required": ["name", "required", "allowedPrefixes"],
|
|
21
|
+
"properties": {
|
|
22
|
+
"name": {
|
|
23
|
+
"type": "string",
|
|
24
|
+
"minLength": 1,
|
|
25
|
+
"description": "Human-readable team name (informational; the key is canonical)."
|
|
26
|
+
},
|
|
27
|
+
"required": {
|
|
28
|
+
"type": "array",
|
|
29
|
+
"description": "List of required label-prefix groups; each group must be satisfied for a write to succeed.",
|
|
30
|
+
"items": {
|
|
31
|
+
"type": "object",
|
|
32
|
+
"additionalProperties": false,
|
|
33
|
+
"required": ["prefixes", "min"],
|
|
34
|
+
"properties": {
|
|
35
|
+
"prefixes": {
|
|
36
|
+
"type": "array",
|
|
37
|
+
"items": { "type": "string", "minLength": 1 },
|
|
38
|
+
"description": "Any label whose name starts with one of these prefixes counts toward this group."
|
|
39
|
+
},
|
|
40
|
+
"min": {
|
|
41
|
+
"type": "integer",
|
|
42
|
+
"minimum": 0,
|
|
43
|
+
"description": "Minimum total label count across the listed prefixes."
|
|
44
|
+
},
|
|
45
|
+
"max": {
|
|
46
|
+
"type": ["integer", "null"],
|
|
47
|
+
"description": "Maximum total count, or null for no upper bound."
|
|
48
|
+
},
|
|
49
|
+
"description": {
|
|
50
|
+
"type": "string",
|
|
51
|
+
"description": "Human-readable hint surfaced in error responses."
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
"allowedPrefixes": {
|
|
57
|
+
"type": "array",
|
|
58
|
+
"items": { "type": "string" },
|
|
59
|
+
"description": "Master list of label prefixes valid for this team. Used for grouping in context responses."
|
|
60
|
+
},
|
|
61
|
+
"requiresProject": {
|
|
62
|
+
"type": "boolean",
|
|
63
|
+
"description": "If true (default), every new issue on this team must have a project set; `issues create` exits 2 with a structured ProjectValidationError when --project is omitted. Set false to allow issues without a project. Teams with zero projects available auto-pass regardless. Bypass per-call with --skip-project-check."
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
"additionalProperties": false
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
"required": ["policies"]
|
|
72
|
+
}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Postinstall hook for @elnora-ai/linear.
|
|
3
|
+
//
|
|
4
|
+
// Goal: after the user installs the package, automatically populate the
|
|
5
|
+
// reference files (teams/projects/users/workflows) from their Linear workspace
|
|
6
|
+
// so the agents and slash commands are personalised on first use — without
|
|
7
|
+
// requiring a manual `elnora-linear sync all` step.
|
|
8
|
+
//
|
|
9
|
+
// Behaviour:
|
|
10
|
+
// - If no API key is reachable, print a friendly notice telling the user how
|
|
11
|
+
// to enable the sync. Never block the install.
|
|
12
|
+
// - If a key is reachable (LINEAR_API_KEY env var, or already saved in
|
|
13
|
+
// ~/.config/elnora-linear/.env), run `sync all` with a hard timeout.
|
|
14
|
+
// Network/API failures degrade to a printed notice.
|
|
15
|
+
// - Always exits 0. A postinstall hook that fails the install is worse than
|
|
16
|
+
// no postinstall hook at all.
|
|
17
|
+
//
|
|
18
|
+
// Escape hatches (set any of these to skip the auto-sync entirely):
|
|
19
|
+
// - ELNORA_LINEAR_SKIP_POSTINSTALL=1
|
|
20
|
+
// - CI=true (most CI systems set this)
|
|
21
|
+
// - npm_config_global=false (local installs in a project)
|
|
22
|
+
//
|
|
23
|
+
// The "local install" skip prevents this from firing on every fresh
|
|
24
|
+
// node_modules in CI builds, monorepo workspaces, Docker layer caches, etc.
|
|
25
|
+
// Global installs (`npm install -g @elnora-ai/linear`) are the user-facing
|
|
26
|
+
// path we want to personalise.
|
|
27
|
+
|
|
28
|
+
import { spawn } from "node:child_process";
|
|
29
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
30
|
+
import { homedir } from "node:os";
|
|
31
|
+
import { dirname, join } from "node:path";
|
|
32
|
+
import { fileURLToPath } from "node:url";
|
|
33
|
+
|
|
34
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
35
|
+
const __dirname = dirname(__filename);
|
|
36
|
+
const PACKAGE_ROOT = dirname(__dirname);
|
|
37
|
+
const CLI_ENTRY = join(PACKAGE_ROOT, "dist", "cli.js");
|
|
38
|
+
const ENV_FILE = join(homedir(), ".config", "elnora-linear", ".env");
|
|
39
|
+
|
|
40
|
+
const SYNC_TIMEOUT_MS = 60_000;
|
|
41
|
+
|
|
42
|
+
const ESC = "\x1b[";
|
|
43
|
+
const useColor = () => process.stdout.isTTY && !process.env.NO_COLOR;
|
|
44
|
+
const COLORS = {
|
|
45
|
+
dim: (s) => (useColor() ? `${ESC}2m${s}${ESC}0m` : s),
|
|
46
|
+
yellow: (s) => (useColor() ? `${ESC}33m${s}${ESC}0m` : s),
|
|
47
|
+
green: (s) => (useColor() ? `${ESC}32m${s}${ESC}0m` : s),
|
|
48
|
+
cyan: (s) => (useColor() ? `${ESC}36m${s}${ESC}0m` : s),
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
function log(line) {
|
|
52
|
+
process.stdout.write(`${line}\n`);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function shouldSkip(env = process.env) {
|
|
56
|
+
if (env.ELNORA_LINEAR_SKIP_POSTINSTALL === "1") {
|
|
57
|
+
return "ELNORA_LINEAR_SKIP_POSTINSTALL=1 is set";
|
|
58
|
+
}
|
|
59
|
+
if (env.CI === "true" || env.CI === "1") {
|
|
60
|
+
return "running in CI";
|
|
61
|
+
}
|
|
62
|
+
// npm sets npm_config_global=true for `-g` installs. Anything else (a local
|
|
63
|
+
// install, a yarn workspace, a pnpm dep resolution) skips. Note: npm sets
|
|
64
|
+
// the env var as a literal string.
|
|
65
|
+
if (env.npm_config_global !== undefined && env.npm_config_global !== "true") {
|
|
66
|
+
return "not a global install";
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function findApiKey(env = process.env, envFile = ENV_FILE) {
|
|
72
|
+
const raw = env.LINEAR_API_KEY?.trim().replace(/^["']|["']$/g, "");
|
|
73
|
+
if (raw?.startsWith("lin_api_")) {
|
|
74
|
+
return { source: "env", value: raw };
|
|
75
|
+
}
|
|
76
|
+
if (existsSync(envFile)) {
|
|
77
|
+
try {
|
|
78
|
+
const content = readFileSync(envFile, "utf8");
|
|
79
|
+
for (const line of content.split("\n")) {
|
|
80
|
+
const match = line.match(/^LINEAR_API_KEY\s*=\s*(.+?)\s*$/);
|
|
81
|
+
if (match) {
|
|
82
|
+
const value = match[1].replace(/^["']|["']$/g, "");
|
|
83
|
+
if (value.startsWith("lin_api_")) {
|
|
84
|
+
return { source: envFile, value };
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
} catch {
|
|
89
|
+
// Unreadable env file — fall through to no-key.
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function printNoKeyNotice() {
|
|
96
|
+
log("");
|
|
97
|
+
log(COLORS.yellow("⚠ elnora-linear: could not personalise your Linear agents."));
|
|
98
|
+
log("");
|
|
99
|
+
log(" No Linear API key was found, so the reference files");
|
|
100
|
+
log(" (teams, projects, users, workflows) were not populated from");
|
|
101
|
+
log(" your Linear workspace.");
|
|
102
|
+
log("");
|
|
103
|
+
log(" To finish setup:");
|
|
104
|
+
log(` 1. Get a key at ${COLORS.cyan("https://linear.app/settings/api")}`);
|
|
105
|
+
log(` 2. ${COLORS.cyan("export LINEAR_API_KEY=lin_api_...")}`);
|
|
106
|
+
log(` 3. ${COLORS.cyan("elnora-linear sync all")}`);
|
|
107
|
+
log("");
|
|
108
|
+
log(COLORS.dim(" (Skip this notice with ELNORA_LINEAR_SKIP_POSTINSTALL=1.)"));
|
|
109
|
+
log("");
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function printFailureNotice(reason) {
|
|
113
|
+
log("");
|
|
114
|
+
log(COLORS.yellow("⚠ elnora-linear: auto-sync did not complete."));
|
|
115
|
+
log(` ${reason}`);
|
|
116
|
+
log("");
|
|
117
|
+
log(` You can rerun it any time: ${COLORS.cyan("elnora-linear sync all")}`);
|
|
118
|
+
log("");
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function printSuccessNotice() {
|
|
122
|
+
log("");
|
|
123
|
+
log(COLORS.green("✓ elnora-linear: reference files populated from your Linear workspace."));
|
|
124
|
+
log(COLORS.dim(" (teams, projects, users, workflows — refresh any time with `elnora-linear sync all`.)"));
|
|
125
|
+
log("");
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function runSync(apiKey, cliEntry = CLI_ENTRY, timeoutMs = SYNC_TIMEOUT_MS) {
|
|
129
|
+
return new Promise((resolve) => {
|
|
130
|
+
if (!existsSync(cliEntry)) {
|
|
131
|
+
resolve({ ok: false, reason: `CLI entry not found at ${cliEntry}` });
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
const child = spawn(process.execPath, [cliEntry, "sync", "all", "--output", "json"], {
|
|
135
|
+
env: { ...process.env, LINEAR_API_KEY: apiKey },
|
|
136
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
137
|
+
});
|
|
138
|
+
let stderr = "";
|
|
139
|
+
child.stderr.on("data", (chunk) => {
|
|
140
|
+
stderr += chunk.toString();
|
|
141
|
+
});
|
|
142
|
+
// Drain stdout so the child doesn't block on a full pipe buffer.
|
|
143
|
+
child.stdout.on("data", () => {});
|
|
144
|
+
|
|
145
|
+
const timer = setTimeout(() => {
|
|
146
|
+
child.kill("SIGTERM");
|
|
147
|
+
resolve({ ok: false, reason: `sync timed out after ${timeoutMs / 1000}s` });
|
|
148
|
+
}, timeoutMs);
|
|
149
|
+
|
|
150
|
+
child.on("error", (err) => {
|
|
151
|
+
clearTimeout(timer);
|
|
152
|
+
resolve({ ok: false, reason: err.message });
|
|
153
|
+
});
|
|
154
|
+
child.on("exit", (code) => {
|
|
155
|
+
clearTimeout(timer);
|
|
156
|
+
if (code === 0) {
|
|
157
|
+
resolve({ ok: true });
|
|
158
|
+
} else {
|
|
159
|
+
const tail = stderr.trim().split("\n").slice(-3).join(" | ") || `exit ${code}`;
|
|
160
|
+
resolve({ ok: false, reason: tail });
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
async function main() {
|
|
167
|
+
if (shouldSkip()) {
|
|
168
|
+
// Silent on skip — postinstall noise during CI/local installs is annoying.
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const key = findApiKey();
|
|
173
|
+
if (!key) {
|
|
174
|
+
printNoKeyNotice();
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const result = await runSync(key.value);
|
|
179
|
+
if (result.ok) {
|
|
180
|
+
printSuccessNotice();
|
|
181
|
+
} else {
|
|
182
|
+
printFailureNotice(result.reason);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Only run when invoked directly (not when imported by tests).
|
|
187
|
+
const invokedDirectly = process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1];
|
|
188
|
+
if (invokedDirectly) {
|
|
189
|
+
main().catch((err) => {
|
|
190
|
+
// Truly defensive: any uncaught error must not fail the install.
|
|
191
|
+
printFailureNotice(err?.message ?? String(err));
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export const _internal = { runSync, ENV_FILE, CLI_ENTRY };
|
|
@@ -28,9 +28,11 @@ Router for Linear work. Dispatches to specialized agents or slash commands rathe
|
|
|
28
28
|
| Refresh reference data from Linear | Slash command: `/linear-sync` |
|
|
29
29
|
| Run the curator (collect signals from external sources) | Slash command: `/linear-curator-run` |
|
|
30
30
|
|
|
31
|
+
For parallel work (e.g. 5 issues from 5 URLs), dispatch multiple agents in a single message — that's why they exist.
|
|
32
|
+
|
|
31
33
|
## First-run install
|
|
32
34
|
|
|
33
|
-
1.
|
|
35
|
+
1. `/plugin marketplace add Elnora-AI/elnora-linear` then `/plugin install linear-workspace@elnora-linear`
|
|
34
36
|
2. Make sure the `elnora-linear` CLI is on your PATH: `npm install -g @elnora-ai/linear`
|
|
35
37
|
3. On your first Linear command, you'll be prompted for your Linear API key (get one at https://linear.app/settings/api). It's saved to `~/.config/elnora-linear/.env` (mode 0600).
|
|
36
38
|
4. Populate the reference files: `/linear-sync` (runs `elnora-linear sync all` — fetches teams, projects, users, workflows in one batch).
|
|
@@ -40,13 +42,72 @@ Router for Linear work. Dispatches to specialized agents or slash commands rathe
|
|
|
40
42
|
The plugin reads user-specific config from `~/.config/elnora-linear/` by default (override via `LINEAR_REFERENCES_DIR`):
|
|
41
43
|
|
|
42
44
|
- `teams.json`, `projects.json`, `users.json`, `workflows.json` — populated by `/linear-sync`
|
|
43
|
-
- `slack.json`, `repos.json`, `signal-sources.json` — populated manually in
|
|
45
|
+
- `slack.json`, `repos.json`, `signal-sources.json`, `label-policy.json` — populated manually (schemas in [`schemas/`](../../schemas/), examples in [`references/*.example.json`](../../references/))
|
|
44
46
|
|
|
45
47
|
Run `elnora-linear sync verify` to see which are populated vs placeholder.
|
|
46
48
|
|
|
49
|
+
## Dispatch prompt — what to include
|
|
50
|
+
|
|
51
|
+
1. The user's raw request, verbatim
|
|
52
|
+
2. Suspected team (let the agent confirm via `elnora-linear teams list`)
|
|
53
|
+
3. Compliance flag (see below), if any
|
|
54
|
+
4. Anything the user already specified (project, priority, assignee, due date)
|
|
55
|
+
5. **If a URL appears anywhere in the request → dispatch to `linear-url-to-issues`**, not `linear-issue-creator`
|
|
56
|
+
|
|
57
|
+
The agent handles searching for duplicates, label requirements, state matching, and asking the user about anything unclear.
|
|
58
|
+
|
|
59
|
+
### Fast-path saves tokens
|
|
60
|
+
|
|
61
|
+
The creator agent has a fast path that skips the dupe scan, project-status check, and reference reads when the dispatch already specifies team + project + priority + assignee + a clear novel title (and no compliance keywords). When you have all five, write them out explicitly in the prompt — the agent will detect the fast path and complete in roughly one CLI call instead of three.
|
|
62
|
+
|
|
63
|
+
### Compliance flag
|
|
64
|
+
|
|
65
|
+
If the request mentions any of: **incident, breach, vulnerability, CVE, pentest, penetration test, onboarding, offboarding, access provision/revoke, audit, SOC 2, change request, risk assessment, vendor review, backup test, RCA, lessons learned, DPA, DSR / data subject request** — say so in the dispatch prompt. The agent will load `references/template-index.md` and apply the matching template (`SEC-*`, `CHG-*`, `ACC-*`, `AUD-*`, `RSK-*`, `OPS-*`, `SLA-*`, `RCA-*`, `LRN-*`).
|
|
66
|
+
|
|
67
|
+
### Model tiering — pass `model:` on the Agent dispatch
|
|
68
|
+
|
|
69
|
+
Match the model to task complexity. The agent frontmatter sets the default; override per-dispatch when the task is clearly easier or harder. Haiku < Sonnet < Opus on cost AND token usage — Opus uses **more** tokens than Sonnet for the same task, not fewer. It's a quality escalation, never a token-saving move.
|
|
70
|
+
|
|
71
|
+
| Task | Agent | Model | Why |
|
|
72
|
+
|---|---|---|---|
|
|
73
|
+
| Fast-path create (all fields explicit, no compliance) | `linear-issue-creator` | `haiku` | Mechanical CRUD, single CLI call |
|
|
74
|
+
| Full-path create (ambiguous routing, dupe scan, compliance template) | `linear-issue-creator` | `sonnet` | Branching + judgment |
|
|
75
|
+
| Single-field update (state, assignee, priority, label add) | `linear-issue-updater` | `haiku` | One CLI call, fixed flag |
|
|
76
|
+
| Cross-team move, full description rewrite | `linear-issue-updater` | `sonnet` | Validates required labels across teams |
|
|
77
|
+
| URL → issues extraction | `linear-url-to-issues` | `sonnet` | Real synthesis from unstructured content |
|
|
78
|
+
| Issue completeness review | `linear-issue-reviewer` | `sonnet` | Reads description + comments + acceptance criteria |
|
|
79
|
+
| Headless curator pass (scheduled) | `linear-state-curator` | `haiku` | Mechanical signal collection + tier dispatch |
|
|
80
|
+
| Interactive curator dry-run / triage | `linear-state-curator` | `sonnet` | Reading curator-report.jsonl + judgment calls on MEDIUM queue |
|
|
81
|
+
|
|
82
|
+
Don't reach for Opus by default. Sonnet handles every Linear task cleanly. Only escalate to Opus if Sonnet has *actually failed* on this task type (looped, produced wrong output, gave up). If the request mentions a compliance keyword, upgrade the creator to Sonnet automatically.
|
|
83
|
+
|
|
84
|
+
### Dispatch prompt budget
|
|
85
|
+
|
|
86
|
+
When the user request is fully specified, keep the dispatch prompt short — the agent already knows the playbook. Pass through:
|
|
87
|
+
|
|
88
|
+
- The user's raw request, verbatim
|
|
89
|
+
- Team / project / priority / assignee if explicit
|
|
90
|
+
- Compliance flag if relevant
|
|
91
|
+
|
|
92
|
+
Don't re-format the description, don't restate the playbook, don't tell the agent how to structure its output. A 100-token dispatch prompt is fine; a 500-token one wastes tokens with no quality gain.
|
|
93
|
+
|
|
94
|
+
## Cold-start primitive
|
|
95
|
+
|
|
96
|
+
For workflows that need team metadata up front (e.g. extracting N issues from a URL into one team), the parent should suggest the agent call `elnora-linear context --team "<Team>"` ONCE before iterating. The response contains projects with statuses, workflow states, the full label catalog grouped by prefix, the required-label policy, and active members — replacing four separate calls (`teams get` + `projects list --team` + `states list --team` + `labels list --team`) and eliminating every reference-file read.
|
|
97
|
+
|
|
98
|
+
The CLI is the source of truth for label policy: `elnora-linear projects get` and `elnora-linear teams get` both return `requiredLabels` and `validStates` directly. `elnora-linear issues create` rejects invalid label combinations with a structured error (`missing`, `availableForPrefix`, `suggestedRetry`) so the agent can self-correct in one retry without reading any reference file.
|
|
99
|
+
|
|
47
100
|
## Safety guardrails
|
|
48
101
|
|
|
49
|
-
- `bulk` and `cleanup` default to **dry-run
|
|
102
|
+
- `bulk` and `cleanup` default to **dry-run** — they print what would change and require `--yes` to commit
|
|
50
103
|
- `bulk` requires at least one of `--set-state` or `--add-comment` — refuses no-op invocations
|
|
51
104
|
- `cleanup` defaults to `comment` action (least destructive); `close` / `cancel` are explicit opt-ins
|
|
52
|
-
- `external_command` signal sources run user-configured commands with the user's privileges — only configure commands from sources
|
|
105
|
+
- `external_command` signal sources run user-configured commands with the user's privileges — only configure commands from sources you trust
|
|
106
|
+
- Permanent deletes need an explicit `--yes` at the CLI layer — a prompt-injected agent cannot bypass it
|
|
107
|
+
- Full guarantees and gated commands documented in [SAFETY.md](../../SAFETY.md)
|
|
108
|
+
|
|
109
|
+
## Don't
|
|
110
|
+
|
|
111
|
+
- Don't read reference `.md` files for label requirements — required-label policy is enforced server-side by the CLI
|
|
112
|
+
- Don't run the create/update workflow inline. The agent owns it.
|
|
113
|
+
- Don't pick a team without confirming via `elnora-linear teams list` or `references/teams.json`
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# ACC-PRO: Access Provisioning
|
|
2
|
+
|
|
3
|
+
## Quick Reference
|
|
4
|
+
- **SLA:** Same day
|
|
5
|
+
- **Team:** *the team that owns this workflow in your workspace*
|
|
6
|
+
- **Project:** Access Provisioning
|
|
7
|
+
|
|
8
|
+
## Required Labels
|
|
9
|
+
- `Type: feature`
|
|
10
|
+
- `Account Setup` (7-day SLA)
|
|
11
|
+
- `Layer: devops`
|
|
12
|
+
|
|
13
|
+
## Issue Template
|
|
14
|
+
```markdown
|
|
15
|
+
## Access Provisioning Request
|
|
16
|
+
|
|
17
|
+
**Request ID:** ACC-PRO-YYYY-XXX
|
|
18
|
+
**Request Date:** [YYYY-MM-DD]
|
|
19
|
+
**Required By Date:** [Start date - access cannot be granted earlier]
|
|
20
|
+
|
|
21
|
+
## Employee/Contractor Information
|
|
22
|
+
- **Name:** [Full name]
|
|
23
|
+
- **Role/Title:** [Job title]
|
|
24
|
+
- **Department:** [Department/Team]
|
|
25
|
+
- **Manager:** [Manager name]
|
|
26
|
+
- **Employment Type:** [Employee / Contractor]
|
|
27
|
+
- **Start Date:** [YYYY-MM-DD]
|
|
28
|
+
- **End Date:** [If contractor - YYYY-MM-DD]
|
|
29
|
+
|
|
30
|
+
## HR Verification Checklist
|
|
31
|
+
- [ ] Signed employment/contractor agreement received
|
|
32
|
+
- [ ] IP agreement signed
|
|
33
|
+
- [ ] Security policy acknowledgment signed
|
|
34
|
+
- [ ] Background check complete (if applicable)
|
|
35
|
+
|
|
36
|
+
## Access Requirements
|
|
37
|
+
|
|
38
|
+
### System Access
|
|
39
|
+
| System | Access Level | Justification | Data Owner Approval |
|
|
40
|
+
|--------|--------------|---------------|---------------------|
|
|
41
|
+
| Google Workspace | [Standard/Admin] | | [ ] |
|
|
42
|
+
| GitHub | [Read/Write/Admin] | | [ ] |
|
|
43
|
+
| AWS | [Specific roles] | | [ ] |
|
|
44
|
+
| Linear | [Member/Admin] | | [ ] |
|
|
45
|
+
| Slack | [Member] | | [ ] |
|
|
46
|
+
| [Other] | | | [ ] |
|
|
47
|
+
|
|
48
|
+
### Privileged Access (if any)
|
|
49
|
+
[If elevated access needed, create linked ACC-PRV issue]
|
|
50
|
+
|
|
51
|
+
## Segregation of Duties Check
|
|
52
|
+
- [ ] Verified no conflicting access combinations
|
|
53
|
+
- [ ] No violations of separation of duties policy
|
|
54
|
+
|
|
55
|
+
## Approvals
|
|
56
|
+
- [ ] HR verification complete: _________________ Date: _______
|
|
57
|
+
- [ ] Manager approval: _________________ Date: _______
|
|
58
|
+
- [ ] System owner approval(s) obtained
|
|
59
|
+
|
|
60
|
+
## Provisioning Checklist
|
|
61
|
+
- [ ] Google Workspace account created
|
|
62
|
+
- [ ] Added to appropriate Google Groups
|
|
63
|
+
- [ ] GitHub organization membership
|
|
64
|
+
- [ ] AWS IAM user/role configured
|
|
65
|
+
- [ ] MFA enrollment required/verified
|
|
66
|
+
- [ ] Linear workspace access
|
|
67
|
+
- [ ] Slack workspace access
|
|
68
|
+
- [ ] Welcome email sent with access instructions
|
|
69
|
+
- [ ] Security training assigned
|
|
70
|
+
|
|
71
|
+
## Verification
|
|
72
|
+
- [ ] User confirmed access working
|
|
73
|
+
- [ ] Access logged in provisioning records
|
|
74
|
+
```
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# ACC-PRV: Privileged Access Request
|
|
2
|
+
|
|
3
|
+
## Quick Reference
|
|
4
|
+
- **SLA:** Same day
|
|
5
|
+
- **Team:** *the team that owns this workflow in your workspace*
|
|
6
|
+
- **Project:** Privileged Access
|
|
7
|
+
|
|
8
|
+
## Required Labels
|
|
9
|
+
- `Type: feature`
|
|
10
|
+
- `Flag: security`
|
|
11
|
+
- `Layer: devops`
|
|
12
|
+
- `Access Request`
|
|
13
|
+
|
|
14
|
+
## Issue Template
|
|
15
|
+
```markdown
|
|
16
|
+
## Privileged Access Request
|
|
17
|
+
|
|
18
|
+
**Request ID:** ACC-PRV-YYYY-XXX
|
|
19
|
+
**Request Date:** [YYYY-MM-DD]
|
|
20
|
+
**Urgency:** [Urgent / Standard]
|
|
21
|
+
|
|
22
|
+
## Requestor Information
|
|
23
|
+
- **Name:** [Full name]
|
|
24
|
+
- **Role:** [Job title]
|
|
25
|
+
- **Department:** [Team]
|
|
26
|
+
- **Manager:** [Manager name]
|
|
27
|
+
|
|
28
|
+
## Access Details
|
|
29
|
+
- **System:** [System requiring privileged access]
|
|
30
|
+
- **Privilege Level:** [Specific privilege - admin, root, etc.]
|
|
31
|
+
- **Current Access:** [What access user currently has]
|
|
32
|
+
- **Requested Access:** [Specific new privileges needed]
|
|
33
|
+
|
|
34
|
+
## Business Justification
|
|
35
|
+
[Detailed explanation of why privileged access is needed]
|
|
36
|
+
|
|
37
|
+
## Duration
|
|
38
|
+
- **Access Type:** [Temporary / Permanent]
|
|
39
|
+
- **Start Date:** [YYYY-MM-DD]
|
|
40
|
+
- **End Date:** [YYYY-MM-DD or "Ongoing until role change"]
|
|
41
|
+
- **Revocation Trigger:** [What event should trigger access removal]
|
|
42
|
+
|
|
43
|
+
## Competency Verification
|
|
44
|
+
- [ ] User has completed security training
|
|
45
|
+
- [ ] User understands privileged access responsibilities
|
|
46
|
+
- [ ] User acknowledges logging of all privileged actions
|
|
47
|
+
|
|
48
|
+
## Security Requirements
|
|
49
|
+
- [ ] MFA will be configured for privileged access
|
|
50
|
+
- [ ] Access will be time-bound when possible
|
|
51
|
+
- [ ] All privileged actions will be logged
|
|
52
|
+
|
|
53
|
+
## Approvals
|
|
54
|
+
- [ ] Manager approval: _________________ Date: _______
|
|
55
|
+
- [ ] System owner approval: _________________ Date: _______
|
|
56
|
+
- [ ] Security review (for admin/root): _________________ Date: _______
|
|
57
|
+
|
|
58
|
+
## Provisioning
|
|
59
|
+
- [ ] Privileged access configured
|
|
60
|
+
- [ ] MFA verified active
|
|
61
|
+
- [ ] User notified of access and responsibilities
|
|
62
|
+
- [ ] Access logged in privileged account register
|
|
63
|
+
|
|
64
|
+
## Review Schedule
|
|
65
|
+
Next review date: [Date - privileged access reviewed quarterly]
|
|
66
|
+
```
|