cli-login 0.1.0__tar.gz

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 (127) hide show
  1. cli_login-0.1.0/.claude/settings.json +10 -0
  2. cli_login-0.1.0/.cursorignore +2 -0
  3. cli_login-0.1.0/.github/workflows/release.yml +66 -0
  4. cli_login-0.1.0/.github/workflows/tests.yml +72 -0
  5. cli_login-0.1.0/.gitignore +6 -0
  6. cli_login-0.1.0/.kanbus.yml +185 -0
  7. cli_login-0.1.0/.vscode/settings.json +14 -0
  8. cli_login-0.1.0/AGENTS.md +51 -0
  9. cli_login-0.1.0/CONTRIBUTING_AGENT.md +475 -0
  10. cli_login-0.1.0/CONTRIBUTING_AGENT.template.md +252 -0
  11. cli_login-0.1.0/LICENSE +21 -0
  12. cli_login-0.1.0/PKG-INFO +104 -0
  13. cli_login-0.1.0/README.md +88 -0
  14. cli_login-0.1.0/docs/design.md +210 -0
  15. cli_login-0.1.0/docs/protocol.md +153 -0
  16. cli_login-0.1.0/features/environment.py +7 -0
  17. cli_login-0.1.0/features/locks.feature +39 -0
  18. cli_login-0.1.0/features/login_session.feature +65 -0
  19. cli_login-0.1.0/features/oauth_provider.feature +21 -0
  20. cli_login-0.1.0/features/remote_sign_in.feature +77 -0
  21. cli_login-0.1.0/features/steps/locks_steps.py +139 -0
  22. cli_login-0.1.0/features/steps/login_session_steps.py +202 -0
  23. cli_login-0.1.0/features/steps/oauth_provider_steps.py +75 -0
  24. cli_login-0.1.0/features/steps/remote_sign_in_steps.py +331 -0
  25. cli_login-0.1.0/features/steps/store_common_steps.py +47 -0
  26. cli_login-0.1.0/features/steps/stores_agent_steps.py +221 -0
  27. cli_login-0.1.0/features/steps/stores_kernel_keyring_steps.py +48 -0
  28. cli_login-0.1.0/features/steps/stores_macos_steps.py +50 -0
  29. cli_login-0.1.0/features/steps/stores_secret_service_steps.py +62 -0
  30. cli_login-0.1.0/features/steps/stores_selection_steps.py +125 -0
  31. cli_login-0.1.0/features/steps/stores_windows_steps.py +100 -0
  32. cli_login-0.1.0/features/steps/target_steps.py +61 -0
  33. cli_login-0.1.0/features/stores_agent.feature +66 -0
  34. cli_login-0.1.0/features/stores_agent_windows.feature +7 -0
  35. cli_login-0.1.0/features/stores_kernel_keyring.feature +53 -0
  36. cli_login-0.1.0/features/stores_macos.feature +17 -0
  37. cli_login-0.1.0/features/stores_secret_service.feature +52 -0
  38. cli_login-0.1.0/features/stores_selection.feature +62 -0
  39. cli_login-0.1.0/features/stores_windows.feature +77 -0
  40. cli_login-0.1.0/features/target.feature +21 -0
  41. cli_login-0.1.0/infra/broker.yaml +164 -0
  42. cli_login-0.1.0/infra/broker_template_test.py +33 -0
  43. cli_login-0.1.0/project/AGENTS.md +6 -0
  44. cli_login-0.1.0/project/events/2026-10-30T10-52-21.293Z__b9260b7c-7ee0-4df4-a3e0-618bf6410f7f.json +18 -0
  45. cli_login-0.1.0/project/events/2026-10-30T10-52-21.309Z__8329b8bd-f933-4597-b6ef-11d3b9e83819.json +18 -0
  46. cli_login-0.1.0/project/events/2026-10-30T10-52-21.319Z__02962f12-cc16-413f-94b1-9ac250cfe43a.json +18 -0
  47. cli_login-0.1.0/project/events/2026-10-30T10-52-21.329Z__78d07504-8941-45fc-aa87-a883260179b6.json +18 -0
  48. cli_login-0.1.0/project/events/2026-10-30T10-52-21.339Z__e2e9e373-9425-47cc-ab2e-97bd17a904b3.json +18 -0
  49. cli_login-0.1.0/project/events/2026-10-30T10-52-21.350Z__811313ad-5bef-4918-a09b-0c6fbee06c27.json +18 -0
  50. cli_login-0.1.0/project/events/2026-10-30T10-52-21.363Z__92385224-7ace-40cd-9f1f-09f3a491c086.json +18 -0
  51. cli_login-0.1.0/project/events/2026-10-30T10-53-42.529Z__b801b764-9abb-4714-9c9a-57f98ec6b120.json +12 -0
  52. cli_login-0.1.0/project/events/2026-10-30T11-43-05.049Z__5f67cee7-ed11-4602-b91a-cc0dc054a000.json +12 -0
  53. cli_login-0.1.0/project/events/2026-10-30T11-43-05.062Z__447020e8-b028-4fbe-9207-869e9aff8ee6.json +17 -0
  54. cli_login-0.1.0/project/events/2026-10-30T11-54-51.436Z__48a79b75-ead6-4a2d-a31c-bb9cedbaaabc.json +18 -0
  55. cli_login-0.1.0/project/events/2026-10-30T11-54-51.454Z__222fa29e-fada-4e25-a64d-e259c99cbb24.json +18 -0
  56. cli_login-0.1.0/project/events/2026-10-30T11-54-51.463Z__0f87a247-a94e-4611-a7a5-0a80f16b50a0.json +18 -0
  57. cli_login-0.1.0/project/events/2026-10-30T11-56-05.842Z__3faa8c4c-7c22-41ab-b86c-2e12e622eb6a.json +12 -0
  58. cli_login-0.1.0/project/events/2026-10-30T11-56-05.852Z__9c5e7de9-0269-47d0-9dab-e58850e21ac9.json +12 -0
  59. cli_login-0.1.0/project/events/2026-10-30T11-57-13.140Z__284dc920-8b9e-47e3-b924-4233c908a54e.json +12 -0
  60. cli_login-0.1.0/project/events/2026-10-30T11-57-13.154Z__08903f6c-aab5-4ea7-877c-cc67ed9cf832.json +12 -0
  61. cli_login-0.1.0/project/events/2026-10-30T11-57-13.163Z__9d412c33-67bf-4bd4-83af-0c55e972f94e.json +12 -0
  62. cli_login-0.1.0/project/events/2026-10-30T11-57-13.173Z__ed2149f3-4c1f-43e4-b38d-0f9b295a0234.json +12 -0
  63. cli_login-0.1.0/project/events/2026-10-30T11-57-13.183Z__8cc06e66-99f6-4529-b312-a70cbaff1ca9.json +12 -0
  64. cli_login-0.1.0/project/events/2026-10-30T11-57-13.193Z__3ee6c0c7-52ca-40c3-b7d2-5e0950b0dce2.json +12 -0
  65. cli_login-0.1.0/project/events/2026-10-30T11-58-11.250Z__57d95af6-0bf0-4cc6-b610-82f4c40fbff1.json +12 -0
  66. cli_login-0.1.0/project/events/2026-10-30T12-00-38.672Z__b391bfe3-c3b0-4a9d-8839-1381a6577b91.json +12 -0
  67. cli_login-0.1.0/project/events/2026-10-30T12-00-38.686Z__153c3c9d-7b02-43af-8d50-888e8a9d965d.json +12 -0
  68. cli_login-0.1.0/project/events/2026-10-30T12-07-40.329Z__ba26d852-684d-4347-bae5-d347cb69fddd.json +12 -0
  69. cli_login-0.1.0/project/events/2026-10-30T12-07-40.337Z__602e30d8-8ef7-40f3-9fe6-505e735f3b89.json +17 -0
  70. cli_login-0.1.0/project/events/2026-10-30T12-10-43.690Z__c2398383-7bf7-437e-8b4c-7aba9633cfbc.json +12 -0
  71. cli_login-0.1.0/project/events/2026-10-30T12-10-44.027Z__0644b779-33ed-49c7-91dc-166760f42aae.json +12 -0
  72. cli_login-0.1.0/project/events/2026-10-30T12-28-43.772Z__f550a131-02c7-44c0-b76a-3694222d74a9.json +12 -0
  73. cli_login-0.1.0/project/events/AGENTS.md +6 -0
  74. cli_login-0.1.0/project/events/DO_NOT_EDIT +3 -0
  75. cli_login-0.1.0/project/issues/AGENTS.md +6 -0
  76. cli_login-0.1.0/project/issues/DO_NOT_EDIT +3 -0
  77. cli_login-0.1.0/project/issues/cli-login-04de9a1b-0c3e-4589-b9b5-ae30cd3cdd18.json +28 -0
  78. cli_login-0.1.0/project/issues/cli-login-1b4a091f-2bfc-405c-be6e-b787b4bb4696.json +28 -0
  79. cli_login-0.1.0/project/issues/cli-login-31750ff1-8d69-4b03-b953-82da220c1a9f.json +43 -0
  80. cli_login-0.1.0/project/issues/cli-login-333326d6-56fb-48cc-bee1-b2a349b145a4.json +28 -0
  81. cli_login-0.1.0/project/issues/cli-login-361d5c51-7951-4e46-9c57-a64cb6f8058f.json +28 -0
  82. cli_login-0.1.0/project/issues/cli-login-85e67311-6ca7-4c57-9e44-4d414ebc618f.json +20 -0
  83. cli_login-0.1.0/project/issues/cli-login-96ed2301-f038-4d76-84bb-b670184ab538.json +40 -0
  84. cli_login-0.1.0/project/issues/cli-login-9a02d68d-d3ff-4dfd-a319-2c411f05fddd.json +35 -0
  85. cli_login-0.1.0/project/issues/cli-login-cccc972a-7df2-4795-9f9b-d8805dfc142e.json +20 -0
  86. cli_login-0.1.0/project/issues/cli-login-ff76cbbc-d47b-49d5-91e1-4aa2ae15e99f.json +28 -0
  87. cli_login-0.1.0/project/wiki/index.md +7 -0
  88. cli_login-0.1.0/project/wiki/whats-next.md +11 -0
  89. cli_login-0.1.0/pyproject.toml +40 -0
  90. cli_login-0.1.0/scripts/build_broker.py +30 -0
  91. cli_login-0.1.0/src/cli_login/__init__.py +4 -0
  92. cli_login-0.1.0/src/cli_login/__init___test.py +18 -0
  93. cli_login-0.1.0/src/cli_login/broker/__init__.py +0 -0
  94. cli_login-0.1.0/src/cli_login/broker/handler.py +310 -0
  95. cli_login-0.1.0/src/cli_login/broker/handler_test.py +284 -0
  96. cli_login-0.1.0/src/cli_login/broker/pages.py +175 -0
  97. cli_login-0.1.0/src/cli_login/broker/pages_test.py +135 -0
  98. cli_login-0.1.0/src/cli_login/broker/throttle.py +25 -0
  99. cli_login-0.1.0/src/cli_login/broker/transactions.py +201 -0
  100. cli_login-0.1.0/src/cli_login/broker/transactions_test.py +132 -0
  101. cli_login-0.1.0/src/cli_login/concurrency_test.py +34 -0
  102. cli_login-0.1.0/src/cli_login/errors.py +29 -0
  103. cli_login-0.1.0/src/cli_login/errors_test.py +13 -0
  104. cli_login-0.1.0/src/cli_login/locks.py +111 -0
  105. cli_login-0.1.0/src/cli_login/locks_test.py +84 -0
  106. cli_login-0.1.0/src/cli_login/oauth.py +143 -0
  107. cli_login-0.1.0/src/cli_login/oauth_test.py +80 -0
  108. cli_login-0.1.0/src/cli_login/remote.py +208 -0
  109. cli_login-0.1.0/src/cli_login/remote_test.py +316 -0
  110. cli_login-0.1.0/src/cli_login/session.py +213 -0
  111. cli_login-0.1.0/src/cli_login/session_test.py +225 -0
  112. cli_login-0.1.0/src/cli_login/stores/__init__.py +122 -0
  113. cli_login-0.1.0/src/cli_login/stores/agent.py +466 -0
  114. cli_login-0.1.0/src/cli_login/stores/agent_test.py +211 -0
  115. cli_login-0.1.0/src/cli_login/stores/kernel_keyring.py +202 -0
  116. cli_login-0.1.0/src/cli_login/stores/kernel_keyring_test.py +98 -0
  117. cli_login-0.1.0/src/cli_login/stores/macos.py +177 -0
  118. cli_login-0.1.0/src/cli_login/stores/macos_test.py +72 -0
  119. cli_login-0.1.0/src/cli_login/stores/secret_service.py +112 -0
  120. cli_login-0.1.0/src/cli_login/stores/secret_service_test.py +84 -0
  121. cli_login-0.1.0/src/cli_login/stores/stores_test.py +110 -0
  122. cli_login-0.1.0/src/cli_login/stores/windows.py +211 -0
  123. cli_login-0.1.0/src/cli_login/stores/windows_test.py +131 -0
  124. cli_login-0.1.0/src/cli_login/target.py +101 -0
  125. cli_login-0.1.0/src/cli_login/target_test.py +91 -0
  126. cli_login-0.1.0/src/cli_login/testing.py +258 -0
  127. cli_login-0.1.0/src/cli_login/testing_processes.py +145 -0
@@ -0,0 +1,10 @@
1
+ {
2
+ "permissions": {
3
+ "deny": [
4
+ "Read(./project/issues/**)",
5
+ "Edit(./project/issues/**)",
6
+ "Read(./project/events/**)",
7
+ "Edit(./project/events/**)"
8
+ ]
9
+ }
10
+ }
@@ -0,0 +1,2 @@
1
+ project/issues/
2
+ project/events/
@@ -0,0 +1,66 @@
1
+ name: release
2
+
3
+ # Git Flow: develop is promoted to main by pull request; only main releases.
4
+ on:
5
+ push:
6
+ branches: [main]
7
+
8
+ concurrency:
9
+ group: release
10
+ cancel-in-progress: false
11
+
12
+ jobs:
13
+ release:
14
+ # The version bump commit carries [skip ci], and a push made with the default workflow token never starts
15
+ # another run; this guard is a third safeguard against an endless loop.
16
+ if: "!contains(github.event.head_commit.message, 'chore(release):')"
17
+ runs-on: ubuntu-latest
18
+ permissions:
19
+ contents: write
20
+ outputs:
21
+ released: ${{ steps.version.outputs.released }}
22
+ tag: ${{ steps.version.outputs.tag }}
23
+ steps:
24
+ - uses: actions/checkout@v4
25
+ with:
26
+ ref: main
27
+ fetch-depth: 0
28
+ - uses: actions/setup-python@v5
29
+ with:
30
+ python-version: "3.13"
31
+ - run: python -m pip install "python-semantic-release==9.21.1"
32
+ - name: Version, tag and GitHub release from conventional commits
33
+ id: version
34
+ env:
35
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
36
+ run: |
37
+ git config user.name "github-actions[bot]"
38
+ git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
39
+ before="$(git rev-parse HEAD)"
40
+ semantic-release version --no-changelog
41
+ after="$(git rev-parse HEAD)"
42
+ if [ "$before" = "$after" ]; then
43
+ echo "released=false" >> "$GITHUB_OUTPUT"
44
+ echo "No feat:, fix: or breaking commit since the last release."
45
+ else
46
+ echo "released=true" >> "$GITHUB_OUTPUT"
47
+ echo "tag=$(git describe --tags --abbrev=0)" >> "$GITHUB_OUTPUT"
48
+ fi
49
+
50
+ pypi:
51
+ needs: release
52
+ if: needs.release.outputs.released == 'true'
53
+ runs-on: ubuntu-latest
54
+ environment: pypi
55
+ permissions:
56
+ id-token: write # OIDC trusted publishing; there is no API token or secret.
57
+ steps:
58
+ - uses: actions/checkout@v4
59
+ with:
60
+ ref: ${{ needs.release.outputs.tag }}
61
+ - uses: actions/setup-python@v5
62
+ with:
63
+ python-version: "3.13"
64
+ - run: python -m pip install build
65
+ - run: python -m build
66
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,72 @@
1
+ name: tests
2
+
3
+ on:
4
+ push:
5
+ branches: [develop, main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ python:
10
+ runs-on: ${{ matrix.os }}
11
+ strategy:
12
+ fail-fast: false
13
+ matrix:
14
+ os: [ubuntu-latest, macos-latest, windows-latest]
15
+ python: ["3.10", "3.13"]
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+ - uses: actions/setup-python@v5
19
+ with:
20
+ python-version: ${{ matrix.python }}
21
+ - run: python -m pip install -e ".[dev]"
22
+ - name: Linux extras and a real Secret Service keyring
23
+ if: runner.os == 'Linux'
24
+ run: |
25
+ sudo apt-get update
26
+ sudo apt-get install -y gnome-keyring dbus-x11 libsecret-1-0
27
+ python -m pip install -e ".[dev,linux]"
28
+ - run: python -m ruff check .
29
+ - name: Specs and Gherkin features
30
+ if: runner.os != 'Linux'
31
+ shell: bash
32
+ run: |
33
+ python -m pytest -q -rs
34
+ python -m behave features
35
+ - name: Specs and Gherkin features, with a real Secret Service and kernel keyring
36
+ if: runner.os == 'Linux'
37
+ env:
38
+ # A skipped real backend fails the run instead of passing silently.
39
+ ANTHUS_REQUIRE_REAL: secret-service,kernel-keyring
40
+ run: |
41
+ dbus-run-session -- bash -c '
42
+ set -e
43
+ echo -n "ci-test-password" | gnome-keyring-daemon --unlock --components=secrets > /dev/null
44
+ python -m pytest -q -rs
45
+ python -m behave features
46
+ '
47
+
48
+ wheel:
49
+ runs-on: ubuntu-latest
50
+ steps:
51
+ - uses: actions/checkout@v4
52
+ - uses: actions/setup-python@v5
53
+ with:
54
+ python-version: "3.13"
55
+ - run: python -m pip install build
56
+ - run: python -m build
57
+ - name: The wheel holds no specs and no plaintext test store
58
+ run: |
59
+ python - <<'PY'
60
+ import glob, zipfile
61
+ (wheel,) = glob.glob("dist/*.whl")
62
+ names = zipfile.ZipFile(wheel).namelist()
63
+ bad = [n for n in names if n.endswith("_test.py") or n.endswith("testing_processes.py")]
64
+ assert not bad, f"test files shipped in the wheel: {bad}"
65
+ assert any(n.endswith("cli_login/__init__.py") for n in names), names
66
+ print("wheel ok:", len(names), "files")
67
+ PY
68
+ - name: The installed wheel imports
69
+ run: |
70
+ python -m venv /tmp/wheel-venv
71
+ /tmp/wheel-venv/bin/pip install dist/*.whl
72
+ cd /tmp && /tmp/wheel-venv/bin/python -c "import cli_login; print(cli_login.__file__)"
@@ -0,0 +1,6 @@
1
+ project/.overlay/
2
+ .venv/
3
+ __pycache__/
4
+ *.egg-info/
5
+ dist/
6
+ *.zip
@@ -0,0 +1,185 @@
1
+ project_directory: project
2
+ virtual_projects: {}
3
+ new_issue_project: null
4
+ ignore_paths: []
5
+ console_port: null
6
+ project_key: cli-login
7
+ project_id: d3c92a99-f33d-4d98-a79d-450199042276
8
+ project_management_template: null
9
+ hierarchy:
10
+ - initiative
11
+ - epic
12
+ - task
13
+ - sub-task
14
+ types:
15
+ - bug
16
+ - story
17
+ - chore
18
+ workflows:
19
+ default:
20
+ backlog:
21
+ - open
22
+ - closed
23
+ blocked:
24
+ - in_progress
25
+ - closed
26
+ closed:
27
+ - open
28
+ in_progress:
29
+ - open
30
+ - blocked
31
+ - closed
32
+ open:
33
+ - in_progress
34
+ - closed
35
+ - backlog
36
+ epic:
37
+ closed:
38
+ - open
39
+ in_progress:
40
+ - open
41
+ - closed
42
+ open:
43
+ - in_progress
44
+ - closed
45
+ transition_labels:
46
+ default:
47
+ backlog:
48
+ closed: Drop
49
+ open: Start discovery
50
+ blocked:
51
+ closed: Drop
52
+ in_progress: Unblock
53
+ closed:
54
+ open: Reopen
55
+ in_progress:
56
+ blocked: Block
57
+ closed: Complete
58
+ open: Pause
59
+ open:
60
+ backlog: Back to backlog
61
+ closed: Drop
62
+ in_progress: Start work
63
+ epic:
64
+ closed:
65
+ open: Reopen
66
+ in_progress:
67
+ closed: Complete
68
+ open: Pause
69
+ open:
70
+ closed: Complete
71
+ in_progress: Start
72
+ initial_status: open
73
+ priorities:
74
+ 0:
75
+ name: critical
76
+ color: red
77
+ 1:
78
+ name: high
79
+ color: bright_red
80
+ 2:
81
+ name: medium
82
+ color: yellow
83
+ 3:
84
+ name: low
85
+ color: blue
86
+ 4:
87
+ name: trivial
88
+ color: white
89
+ default_priority: 2
90
+ assignee: null
91
+ time_zone: null
92
+ statuses:
93
+ - key: backlog
94
+ name: Backlog
95
+ category: To do
96
+ semantic_category: todo
97
+ color: null
98
+ collapsed: true
99
+ - key: open
100
+ name: Discovery
101
+ category: To do
102
+ semantic_category: todo
103
+ color: null
104
+ collapsed: false
105
+ - key: in_progress
106
+ name: In Progress
107
+ category: In progress
108
+ semantic_category: in_progress
109
+ color: null
110
+ collapsed: false
111
+ - key: blocked
112
+ name: Blocked
113
+ category: In progress
114
+ semantic_category: in_progress
115
+ color: null
116
+ collapsed: true
117
+ - key: closed
118
+ name: Done
119
+ category: Done
120
+ semantic_category: done
121
+ color: null
122
+ collapsed: true
123
+ categories:
124
+ - name: To do
125
+ color: grey
126
+ - name: In progress
127
+ color: blue
128
+ - name: Done
129
+ color: green
130
+ sort_order: {}
131
+ type_colors:
132
+ bug: red
133
+ chore: green
134
+ epic: magenta
135
+ event: bright_blue
136
+ initiative: bright_blue
137
+ story: yellow
138
+ sub-task: bright_cyan
139
+ task: blue
140
+ beads_compatibility: false
141
+ events: true
142
+ wiki_directory: null
143
+ ai:
144
+ provider: litellm
145
+ model: gpt-5.6-luna
146
+ right_now:
147
+ enabled: true
148
+ default_tree_expanded: false
149
+ max_length: 120
150
+ model: gpt-5.6-luna
151
+ standup:
152
+ window: rolling
153
+ lookback: 24h
154
+ skip_weekends: false
155
+ timezone: null
156
+ jira: null
157
+ snyk: null
158
+ realtime:
159
+ transport: auto
160
+ broker: auto
161
+ autostart: false
162
+ keepalive: false
163
+ uds_socket_path: null
164
+ mqtt_custom_authorizer_name: null
165
+ mqtt_api_token: null
166
+ topics:
167
+ project_events: projects/{project}/events
168
+ overlay:
169
+ enabled: true
170
+ ttl_s: 86400
171
+ hooks:
172
+ enabled: true
173
+ run_in_beads_mode: true
174
+ default_timeout_ms: 5000
175
+ before: {}
176
+ after: {}
177
+ github_security: null
178
+ coordination:
179
+ providers:
180
+ - git
181
+ contention_window: 5s
182
+ default_lease_ttl: 300s
183
+ mutex_api:
184
+ endpoint: null
185
+ bearer_token: null
@@ -0,0 +1,14 @@
1
+ {
2
+ "files.exclude": {
3
+ "**/project/issues/**": true,
4
+ "**/project/events/**": true
5
+ },
6
+ "files.watcherExclude": {
7
+ "**/project/issues/**": true,
8
+ "**/project/events/**": true
9
+ },
10
+ "search.exclude": {
11
+ "**/project/issues/**": true,
12
+ "**/project/events/**": true
13
+ }
14
+ }
@@ -0,0 +1,51 @@
1
+ # Agent Instructions
2
+
3
+ ## Project management with Kanbus
4
+
5
+ Use Kanbus for task management.
6
+ Why: Kanbus task management is MANDATORY here; every task must live in Kanbus.
7
+ When: Create/update the Kanbus task before coding; close it only after the change lands.
8
+ How: See CONTRIBUTING_AGENT.md for the Kanbus workflow, hierarchy, status rules, priorities, command examples, and the mistakes to avoid. Never inspect project/ or issue JSON directly (including with cat or jq); use Kanbus commands only.
9
+ Performance: Prefer kbs (Rust) when available; kanbus (Python) is equivalent but slower.
10
+ Warning: Editing project/ directly violates The Way. Do not read or write anything in project/; work only through Kanbus.
11
+ Git / PR policy: Rules for product-code commits, branch names, pull requests, and human approval live in this repository's AGENTS.md (outside this Kanbus section). CONTRIBUTING_AGENT.md covers Kanbus board mechanics such as `kbs commit`; follow AGENTS.md for product code and git workflow.
12
+
13
+
14
+ ## What this project is
15
+
16
+ `cli-login` is the one CLI login shared by Anthus products (Cyclotron, Papyrus, Auritus, and later Chatticus). It
17
+ holds three parts: a Python library for the CLI side, a broker deployed once per product deployment, and a
18
+ language-neutral protocol with conformance specs. Read [docs/design.md](docs/design.md) first.
19
+
20
+ ## Rules that matter here
21
+
22
+ - **This repository is public.** Never commit account ids, user pool ids, client ids, product domains, tokens,
23
+ secrets or real email addresses. Each product supplies its own values through its discovery data. Examples use
24
+ placeholders such as `https://app.example.test`.
25
+ - **Products stay separate.** Every stored key carries the product namespace, and a store refuses a key outside
26
+ the namespace it was opened with. One product never reads, refreshes or revokes another product's credentials.
27
+ - **Fail closed.** No plaintext fallback for any secret, ever. A missing, locked or unusable store is an error with
28
+ recovery guidance.
29
+ - **Never replay an uncertain mutation.** Only token operations are retried.
30
+ - **Specs first.** Every behaviour change ships with Gherkin specs and unit specs beside the module. Specs use fake
31
+ providers, stores and brokers; no network or credentials in specs. Live proof is recorded separately.
32
+ - **Protocol changes are versioned.** A change to the broker protocol bumps the major version, and the broker's
33
+ answers carry it.
34
+ - **Do not print, log or commit secrets.** Status and errors redact every token.
35
+
36
+ ## Git workflow
37
+
38
+ Git Flow: branch from `develop`, open a pull request to `develop`, merge with a merge commit once CI is green.
39
+ Promotion to `main` is a pull request from `develop`. Kanbus board changes are committed on `develop` with
40
+ `kbs commit` and pushed, with no pull request. Conventional commits (`feat:`, `fix:`, `docs:`, `chore:`, `test:`).
41
+
42
+ ## Commands
43
+
44
+ ```bash
45
+ python -m pip install -e ".[dev]"
46
+ python -m ruff check .
47
+ python -m pytest -q # unit specs beside each module
48
+ python -m behave features # Gherkin specs
49
+ ```
50
+
51
+ CI runs these on Linux, macOS and Windows, because the stores and locks differ by platform.