kctl-accurate 0.2.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 (51) hide show
  1. kctl_accurate-0.2.0/.gitignore +33 -0
  2. kctl_accurate-0.2.0/CLAUDE.md +42 -0
  3. kctl_accurate-0.2.0/PKG-INFO +18 -0
  4. kctl_accurate-0.2.0/README.md +79 -0
  5. kctl_accurate-0.2.0/pyproject.toml +51 -0
  6. kctl_accurate-0.2.0/skills/accurate-admin/SKILL.md +173 -0
  7. kctl_accurate-0.2.0/src/kctl_accurate/__init__.py +3 -0
  8. kctl_accurate-0.2.0/src/kctl_accurate/__main__.py +5 -0
  9. kctl_accurate-0.2.0/src/kctl_accurate/cli.py +102 -0
  10. kctl_accurate-0.2.0/src/kctl_accurate/commands/__init__.py +1 -0
  11. kctl_accurate-0.2.0/src/kctl_accurate/commands/auth.py +58 -0
  12. kctl_accurate-0.2.0/src/kctl_accurate/commands/config_cmd.py +196 -0
  13. kctl_accurate-0.2.0/src/kctl_accurate/commands/dashboard.py +90 -0
  14. kctl_accurate-0.2.0/src/kctl_accurate/commands/db.py +89 -0
  15. kctl_accurate-0.2.0/src/kctl_accurate/commands/discover.py +103 -0
  16. kctl_accurate-0.2.0/src/kctl_accurate/commands/doctor_cmd.py +149 -0
  17. kctl_accurate-0.2.0/src/kctl_accurate/commands/export.py +126 -0
  18. kctl_accurate-0.2.0/src/kctl_accurate/commands/extract.py +201 -0
  19. kctl_accurate-0.2.0/src/kctl_accurate/commands/modules.py +245 -0
  20. kctl_accurate-0.2.0/src/kctl_accurate/commands/reports.py +513 -0
  21. kctl_accurate-0.2.0/src/kctl_accurate/commands/statements.py +208 -0
  22. kctl_accurate-0.2.0/src/kctl_accurate/commands/tax.py +210 -0
  23. kctl_accurate-0.2.0/src/kctl_accurate/commands/validate.py +329 -0
  24. kctl_accurate-0.2.0/src/kctl_accurate/core/__init__.py +1 -0
  25. kctl_accurate-0.2.0/src/kctl_accurate/core/callbacks.py +38 -0
  26. kctl_accurate-0.2.0/src/kctl_accurate/core/client.py +114 -0
  27. kctl_accurate-0.2.0/src/kctl_accurate/core/columns.py +178 -0
  28. kctl_accurate-0.2.0/src/kctl_accurate/core/config.py +144 -0
  29. kctl_accurate-0.2.0/src/kctl_accurate/core/exceptions.py +70 -0
  30. kctl_accurate-0.2.0/src/kctl_accurate/core/streaming.py +183 -0
  31. kctl_accurate-0.2.0/tests/__init__.py +0 -0
  32. kctl_accurate-0.2.0/tests/conftest.py +79 -0
  33. kctl_accurate-0.2.0/tests/unit/__init__.py +0 -0
  34. kctl_accurate-0.2.0/tests/unit/test_cli_help.py +25 -0
  35. kctl_accurate-0.2.0/tests/unit/test_cli_version.py +20 -0
  36. kctl_accurate-0.2.0/tests/unit/test_client.py +107 -0
  37. kctl_accurate-0.2.0/tests/unit/test_cmd_auth.py +89 -0
  38. kctl_accurate-0.2.0/tests/unit/test_cmd_config.py +132 -0
  39. kctl_accurate-0.2.0/tests/unit/test_cmd_dashboard.py +117 -0
  40. kctl_accurate-0.2.0/tests/unit/test_cmd_db.py +132 -0
  41. kctl_accurate-0.2.0/tests/unit/test_cmd_doctor.py +83 -0
  42. kctl_accurate-0.2.0/tests/unit/test_cmd_extract.py +121 -0
  43. kctl_accurate-0.2.0/tests/unit/test_cmd_modules.py +242 -0
  44. kctl_accurate-0.2.0/tests/unit/test_cmd_reports.py +259 -0
  45. kctl_accurate-0.2.0/tests/unit/test_cmd_statements.py +119 -0
  46. kctl_accurate-0.2.0/tests/unit/test_cmd_tax.py +114 -0
  47. kctl_accurate-0.2.0/tests/unit/test_cmd_validate.py +181 -0
  48. kctl_accurate-0.2.0/tests/unit/test_columns.py +65 -0
  49. kctl_accurate-0.2.0/tests/unit/test_config.py +128 -0
  50. kctl_accurate-0.2.0/tests/unit/test_exceptions.py +88 -0
  51. kctl_accurate-0.2.0/tests/unit/test_streaming.py +201 -0
@@ -0,0 +1,33 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ *.egg
6
+ dist/
7
+ build/
8
+ .eggs/
9
+
10
+ # Virtual environments
11
+ .venv/
12
+ venv/
13
+
14
+ # IDE
15
+ .idea/
16
+ .vscode/
17
+ *.swp
18
+ *.swo
19
+
20
+ # Testing
21
+ .pytest_cache/
22
+ .coverage
23
+ htmlcov/
24
+ .mypy_cache/
25
+ .ruff_cache/
26
+
27
+ # OS
28
+ .DS_Store
29
+ Thumbs.db
30
+
31
+ # Environment
32
+ .env
33
+ .env.local
@@ -0,0 +1,42 @@
1
+ # CLAUDE.md - kctl-accurate
2
+
3
+ Kodemeio CLI for the Accurate Online API.
4
+
5
+ ## Quick start
6
+
7
+ ```bash
8
+ uv sync --all-packages
9
+ uv run --project ../.. pytest packages/kctl-accurate/tests/ -v
10
+ ```
11
+
12
+ ## Architecture
13
+
14
+ ```
15
+ src/kctl_accurate/
16
+ ├── cli.py # Typer app + @app.callback for global flags
17
+ ├── core/
18
+ │ ├── config.py # SERVICE_KEY=accurate, ServiceConfig, resolve_connection
19
+ │ ├── client.py # AccurateClientWrapper translates SDK exceptions
20
+ │ ├── exceptions.py # SDK→KctlError translator (drives exit codes)
21
+ │ └── callbacks.py # AppContext(AppContextBase), lazy client
22
+ └── commands/
23
+ ├── config_cmd.py # init/list/show/use/add/remove/set/test
24
+ ├── auth.py # token-info/refresh/logout
25
+ └── doctor_cmd.py # ConfigCheck + TokenCheck + DbListCheck
26
+ ```
27
+
28
+ ## Key constraints
29
+
30
+ - SERVICE_KEY: `"accurate"` — config at `profiles.<name>.accurate.*`
31
+ - Depends on `kctl-lib>=0.4.0` (workspace) and `kodemeio-accurate>=0.4.0,<1.0.0` (PyPI)
32
+ - All SDK exceptions translated at the wrapper boundary in `core/client.py`
33
+ - Secrets always masked in any non-debug output (per `~/.claude/rules/security.md`)
34
+ - Exit-code contract enforced by `KctlError` subclass (see `core/exceptions.py`)
35
+ - One profile = one tenant. Multi-tenant via multiple profiles, not multi-target invocation.
36
+
37
+ ## What's next
38
+
39
+ - Phase 2: 23 module command groups (`customers list`, `invoices get`, etc.) generated from `core/columns.py:MODULE_REGISTRY`
40
+ - Phase 3: `extract`, `export`, `indo` (e-Faktur + 3 validators + 3 statement extractors)
41
+
42
+ See `kodemeio-accurate/docs/superpowers/specs/2026-04-30-kctl-accurate-design.md` for the full design.
@@ -0,0 +1,18 @@
1
+ Metadata-Version: 2.4
2
+ Name: kctl-accurate
3
+ Version: 0.2.0
4
+ Summary: Kodemeio Accurate Online CLI — general-purpose ops on the Accurate API
5
+ Requires-Python: >=3.12
6
+ Requires-Dist: kctl-lib>=0.4.0
7
+ Requires-Dist: kodemeio-accurate<1.0.0,>=0.4.0
8
+ Requires-Dist: pydantic>=2.10.0
9
+ Requires-Dist: pyyaml>=6.0.2
10
+ Requires-Dist: rich>=13.9.0
11
+ Requires-Dist: typer>=0.15.0
12
+ Provides-Extra: dev
13
+ Requires-Dist: mypy>=1.14.0; extra == 'dev'
14
+ Requires-Dist: pytest-cov>=6.0.0; extra == 'dev'
15
+ Requires-Dist: pytest-httpx>=0.35.0; extra == 'dev'
16
+ Requires-Dist: pytest>=8.3.0; extra == 'dev'
17
+ Requires-Dist: ruff>=0.9.0; extra == 'dev'
18
+ Requires-Dist: types-pyyaml>=6.0.0; extra == 'dev'
@@ -0,0 +1,79 @@
1
+ # kctl-accurate
2
+
3
+ General-purpose CLI for the Accurate Online API. Part of the Kodemeio kctl-* family.
4
+
5
+ > **v0.1.0a1 (alpha)** — Phase 1 walking skeleton: config + auth + doctor only.
6
+ > Module commands (customers, invoices, etc.) ship in 0.1.0 (Phase 2).
7
+ > Extract / Indo commands ship in 0.2.0 (Phase 3).
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ uv tool install kctl-accurate
13
+ # or, from the kodemeio-platform monorepo:
14
+ uv sync --all-packages
15
+ ```
16
+
17
+ ## Quickstart
18
+
19
+ ```bash
20
+ # Interactive: prompts for token, secret, db_id; verifies; saves.
21
+ kctl-accurate config init
22
+
23
+ # Verify creds against the live API
24
+ kctl-accurate config test
25
+
26
+ # Show current token info
27
+ kctl-accurate auth token-info
28
+
29
+ # Diagnose
30
+ kctl-accurate doctor
31
+ ```
32
+
33
+ ## Profiles
34
+
35
+ Multi-tenant via the kctl-* shared config at `~/.config/kodemeio/config.yaml`:
36
+
37
+ ```yaml
38
+ profiles:
39
+ tpp:
40
+ accurate:
41
+ api_token: aut.xxxxx
42
+ signature_secret: ${KCTL_ACCURATE_TPP_SECRET} # env-var indirection works
43
+ db_id: 12345
44
+ host: https://public.accurate.id
45
+ db_alias: PT TPP Indonesia
46
+ ```
47
+
48
+ Use a profile per command: `kctl-accurate -p tpp auth token-info`.
49
+
50
+ ## Global flags
51
+
52
+ | flag | purpose |
53
+ |---|---|
54
+ | `-p, --profile NAME` | Override active profile |
55
+ | `--api-token TOKEN` | Override profile's api_token |
56
+ | `--signature-secret S` | Override profile's signature_secret |
57
+ | `--db-id N` | Override profile's db_id |
58
+ | `--host URL` | Override profile's host |
59
+ | `--json` | JSON output |
60
+ | `-q, --quiet` | Suppress progress/info |
61
+ | `-V, --version` | Print version + exit |
62
+
63
+ ## Exit codes
64
+
65
+ | code | meaning |
66
+ |---|---|
67
+ | 0 | success |
68
+ | 1 | command-level failure |
69
+ | 2 | config error (missing creds, bad profile) |
70
+ | 3 | network/API error (5xx, host unreachable) |
71
+ | 4 | auth error (401/403, signature/token) |
72
+ | 5 | rate-limit exhaustion (429 after retries) |
73
+
74
+ > Note: kctl-lib 0.4.0's `handle_cli_error` currently exits 1 for all KctlError subclasses. The differentiated exit codes above are the *intent* carried by the subclass — they will activate when kctl-lib adds per-subclass exit-code routing or when per-command `_run()` overrides are added.
75
+
76
+ ## Related
77
+
78
+ - [`kodemeio-accurate`](https://pypi.org/project/kodemeio-accurate/) — the Python SDK powering this CLI
79
+ - `accurate-sync` — the migration writer (Accurate → Odoo); separate tool, separate scope
@@ -0,0 +1,51 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "kctl-accurate"
7
+ version = "0.2.0"
8
+ description = "Kodemeio Accurate Online CLI — general-purpose ops on the Accurate API"
9
+ requires-python = ">=3.12"
10
+ dependencies = [
11
+ "kctl-lib>=0.4.0",
12
+ "kodemeio-accurate>=0.4.0,<1.0.0",
13
+ "typer>=0.15.0",
14
+ "rich>=13.9.0",
15
+ "pydantic>=2.10.0",
16
+ "pyyaml>=6.0.2",
17
+ ]
18
+
19
+ [project.optional-dependencies]
20
+ dev = [
21
+ "pytest>=8.3.0",
22
+ "pytest-httpx>=0.35.0",
23
+ "pytest-cov>=6.0.0",
24
+ "ruff>=0.9.0",
25
+ "mypy>=1.14.0",
26
+ "types-PyYAML>=6.0.0",
27
+ ]
28
+
29
+ [project.scripts]
30
+ kctl-accurate = "kctl_accurate.cli:_run"
31
+
32
+ [project.entry-points."kctl_accurate.plugins"]
33
+
34
+ [tool.uv.sources]
35
+ kctl-lib = { workspace = true }
36
+
37
+ [tool.hatch.build.targets.wheel]
38
+ packages = ["src/kctl_accurate"]
39
+
40
+ [tool.ruff]
41
+ target-version = "py312"
42
+ line-length = 120
43
+
44
+ [tool.mypy]
45
+ python_version = "3.12"
46
+ strict = true
47
+ ignore_missing_imports = true
48
+
49
+ [[tool.mypy.overrides]]
50
+ module = ["kctl_lib", "kctl_lib.*", "accurate_sdk", "accurate_sdk.*"]
51
+ follow_imports = "silent"
@@ -0,0 +1,173 @@
1
+ ---
2
+ name: accurate-admin
3
+ description: >
4
+ Accurate Online accounting administration via kctl-accurate CLI (10+ groups, ~30 commands + 23 module groups).
5
+ MUST use for ANY kctl-accurate operation.
6
+ Triggers on: "accurate", "accounting", "auth", "config", "customers", "dashboard", "db", "doctor",
7
+ "efaktur", "export", "extract", "glaccounts", "invoices", "items", "kctl-accurate", "migrate",
8
+ "module", "nsfp", "pph", "profile", "statements", "tax", "validate", "vendors".
9
+ Auto-generated: 2026-05-03
10
+ ---
11
+
12
+ # accurate-admin -- kctl-accurate CLI Reference
13
+
14
+ > Auto-generated from `kctl-accurate` command registry. Do not edit manually.
15
+ > To regenerate: `kctl-accurate skill generate`
16
+ > To add custom content: edit `SKILL.extra.md` in the same directory.
17
+
18
+ ## Overview
19
+
20
+ **CLI:** `kctl-accurate`
21
+ **Command groups:** 10 core + 23 module groups
22
+ **Total commands:** ~30 core + ~69 module (list/get/count per module)
23
+ **Install:** `cd packages/kctl-accurate && uv tool install --editable .`
24
+
25
+ ## Global Options
26
+
27
+ | Flag | Description |
28
+ |------|-------------|
29
+ | `--json` | Output as JSON |
30
+ | `--quiet`, `-q` | Suppress info messages |
31
+ | `--profile`, `-p` | Config profile name |
32
+ | `--api-token` | Override Accurate API token |
33
+ | `--signature-secret` | Override HMAC-SHA256 secret |
34
+ | `--db-id` | Override Accurate company db_id |
35
+ | `--host` | Override Accurate host |
36
+ | `--version`, `-V` | Show version |
37
+
38
+ ## Command Reference
39
+
40
+ ### `kctl-accurate auth`
41
+
42
+ Accurate auth operations: token-info, refresh, logout.
43
+
44
+ | Command | Description |
45
+ |---------|-------------|
46
+ | `auth token-info` | Show current API token info: user, database, host. |
47
+ | `auth refresh` | Refresh the current API session token. |
48
+ | `auth logout` | Invalidate the current API session. |
49
+
50
+ ### `kctl-accurate config`
51
+
52
+ Manage CLI configuration and profiles.
53
+
54
+ | Command | Description |
55
+ |---------|-------------|
56
+ | `config init` | Initialize CLI configuration. |
57
+ | `config show` | Show configuration (keys masked). |
58
+ | `config add` | Add a new profile. |
59
+ | `config use` | Switch default profile. |
60
+ | `config remove` | Remove a profile. |
61
+ | `config set` | Set a config value. |
62
+ | `config test` | Test API connection. |
63
+
64
+ ### `kctl-accurate dashboard`
65
+
66
+ Show a dashboard overview: user info, DB info, and module record counts
67
+ (customers, vendors, items, sales-invoices, purchase-invoices).
68
+
69
+ ### `kctl-accurate db`
70
+
71
+ Accurate database/company operations.
72
+
73
+ | Command | Description |
74
+ |---------|-------------|
75
+ | `db list-companies` | List all Accurate companies accessible with this token. |
76
+ | `db open <db_id>` | Open a database session and print session info. |
77
+ | `db info` | Show current profile's database info (user, DB ID, alias, host). |
78
+
79
+ ### `kctl-accurate extract`
80
+
81
+ Bulk-extract Accurate Online data to JSON files on disk.
82
+
83
+ | Command | Description |
84
+ |---------|-------------|
85
+ | `extract run --out-dir <path> [--modules] [--no-detail] [--resume]` | Extract data (master + transaction modules) to JSON files. |
86
+ | `extract resume --out-dir <path>` | Resume a previous extraction run, skipping already-fetched files. |
87
+
88
+ ### `kctl-accurate export`
89
+
90
+ Convert Accurate Online JSON extracts to Odoo-importable CSV files.
91
+
92
+ | Command | Description |
93
+ |---------|-------------|
94
+ | `export csv --json-dir <path> --out-dir <path> [--modules]` | Convert JSON extracts to Odoo-importable CSV files. |
95
+
96
+ ### `kctl-accurate tax`
97
+
98
+ e-Faktur (DJP) commands -- list and export faktur pajak data.
99
+
100
+ | Command | Description |
101
+ |---------|-------------|
102
+ | `tax efaktur-list [--since] [--period] [--out]` | List faktur pajak records for a date range or calendar period. |
103
+ | `tax efaktur-export-csv --out <path> [--period] [--since]` | Export faktur pajak records to a file (.csv, .jsonl, .json). |
104
+
105
+ ### `kctl-accurate validate`
106
+
107
+ Pre/post-migration data quality checks.
108
+
109
+ | Command | Description |
110
+ |---------|-------------|
111
+ | `validate nsfp` | Check for duplicate NSFP numbers across open AR/AP invoices. |
112
+ | `validate pph --accurate-totals <file> --odoo-totals <file>` | Check PPh withholding consistency (post-migration). |
113
+ | `validate ar-ap --accurate-balances <file> --odoo-balances <file>` | Check AR/AP open-balance parity (post-migration). |
114
+
115
+ ### `kctl-accurate statements`
116
+
117
+ Financial statement extraction (opening BS, YTD BS, YTD P&L).
118
+
119
+ | Command | Description |
120
+ |---------|-------------|
121
+ | `statements opening-bs --as-of <date> [--out]` | Extract opening Balance Sheet at a specific historical date. |
122
+ | `statements ytd-bs [--out]` | Extract year-to-date Balance Sheet (current account balances). |
123
+ | `statements ytd-pl [--out]` | Extract year-to-date Profit & Loss (current account balances). |
124
+
125
+ ### `kctl-accurate doctor`
126
+
127
+ Run diagnostic checks: config, token validity, DB access.
128
+
129
+ ### Module Groups (23 auto-generated)
130
+
131
+ Each module group provides `list`, `get`, and `count` subcommands driven by the `MODULE_REGISTRY`.
132
+
133
+ **Master data:** customers, vendors, items, glaccounts, warehouses, currencies, employees, units, taxes, payment-terms
134
+
135
+ **Sales:** sales-orders, sales-invoices, sales-receipts, delivery-orders
136
+
137
+ **Purchase:** purchase-orders, purchase-invoices, purchase-payments, receive-items
138
+
139
+ **Finance:** journal-vouchers, expenses, bank-transfers, other-deposits, other-payments
140
+
141
+ **Examples:**
142
+ ```bash
143
+ kctl-accurate customers list -p idtpp
144
+ kctl-accurate sales-invoices get 12345 -p idtpp
145
+ kctl-accurate items count -p idtpp
146
+ ```
147
+
148
+ ## Configuration
149
+
150
+ Shared config: `~/.config/kodemeio/config.yaml`
151
+ Service key: `accurate`
152
+
153
+ ```bash
154
+ kctl-accurate config init # Interactive setup
155
+ kctl-accurate config show # Show current config
156
+ kctl-accurate config test # Verify API connection
157
+ kctl-accurate doctor run # Full diagnostics
158
+ ```
159
+
160
+ **Examples:**
161
+ ```bash
162
+ # Extract all modules to JSON
163
+ kctl-accurate extract run --out-dir ./dump -p idtpp
164
+
165
+ # Convert extracted JSON to Odoo CSV
166
+ kctl-accurate export csv --json-dir ./dump --out-dir ./csv -p idtpp
167
+
168
+ # List e-Faktur records for April 2026
169
+ kctl-accurate tax efaktur-list --period 2026-04 -p idtpp
170
+
171
+ # Pre-migration NSFP duplicate check
172
+ kctl-accurate validate nsfp -p idtpp
173
+ ```
@@ -0,0 +1,3 @@
1
+ """Kodemeio Accurate Online CLI."""
2
+
3
+ __version__ = "0.2.0"
@@ -0,0 +1,5 @@
1
+ """Allow running as: python -m kctl_accurate."""
2
+
3
+ from kctl_accurate.cli import _run
4
+
5
+ _run()
@@ -0,0 +1,102 @@
1
+ """Main CLI entry point for kctl-accurate."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Annotated
6
+
7
+ import typer
8
+ from kctl_lib import KctlError, handle_cli_error
9
+
10
+ from kctl_accurate import __version__
11
+ from kctl_accurate.commands.auth import app as auth_app
12
+ from kctl_accurate.commands.config_cmd import app as config_app
13
+ from kctl_accurate.commands.dashboard import app as dashboard_app
14
+ from kctl_accurate.commands.db import app as db_app
15
+ from kctl_accurate.commands.discover import app as discover_app
16
+ from kctl_accurate.commands.doctor_cmd import app as doctor_app
17
+ from kctl_accurate.commands.export import app as export_app
18
+ from kctl_accurate.commands.extract import app as extract_app
19
+ from kctl_accurate.commands.modules import build_module_app
20
+ from kctl_accurate.commands.reports import app as reports_app
21
+ from kctl_accurate.commands.statements import app as statements_app
22
+ from kctl_accurate.commands.tax import app as tax_app
23
+ from kctl_accurate.commands.validate import app as validate_app
24
+ from kctl_accurate.core.callbacks import AppContext
25
+ from kctl_accurate.core.columns import MODULE_REGISTRY
26
+ from kctl_lib.self_update import notify_if_outdated
27
+
28
+
29
+ def version_callback(value: bool) -> None:
30
+ if value:
31
+ typer.echo(f"kctl-accurate {__version__}")
32
+ raise typer.Exit()
33
+
34
+
35
+ app = typer.Typer(
36
+ name="kctl-accurate",
37
+ help="Kodemeio Accurate Online CLI — general-purpose ops on the Accurate API.",
38
+ no_args_is_help=True,
39
+ rich_markup_mode="rich",
40
+ pretty_exceptions_enable=False,
41
+ )
42
+
43
+ app.add_typer(auth_app, name="auth")
44
+ app.add_typer(config_app, name="config")
45
+ app.add_typer(discover_app, name="discover")
46
+ app.add_typer(doctor_app, name="doctor")
47
+ app.add_typer(db_app, name="db")
48
+ app.add_typer(dashboard_app, name="dashboard")
49
+ app.add_typer(extract_app, name="extract")
50
+ app.add_typer(export_app, name="export")
51
+ app.add_typer(tax_app, name="tax")
52
+ app.add_typer(validate_app, name="validate")
53
+ app.add_typer(reports_app, name="reports")
54
+ app.add_typer(statements_app, name="statements")
55
+
56
+ # ── Module groups ─────────────────────────────────────────────────────────────
57
+ for _cli_name, _spec in MODULE_REGISTRY.items():
58
+ app.add_typer(build_module_app(_spec), name=_cli_name)
59
+
60
+
61
+ @app.callback()
62
+ def main(
63
+ ctx: typer.Context,
64
+ json_output: Annotated[bool, typer.Option("--json", help="Output as JSON")] = False,
65
+ quiet: Annotated[bool, typer.Option("--quiet", "-q", help="Suppress info messages")] = False,
66
+ profile: Annotated[str | None, typer.Option("--profile", "-p", help="Config profile name")] = None,
67
+ api_token: Annotated[str | None, typer.Option("--api-token", help="Override Accurate API token")] = None,
68
+ signature_secret: Annotated[
69
+ str | None,
70
+ typer.Option("--signature-secret", help="Override HMAC-SHA256 secret"),
71
+ ] = None,
72
+ db_id: Annotated[int | None, typer.Option("--db-id", help="Override Accurate company db_id")] = None,
73
+ host: Annotated[str | None, typer.Option("--host", help="Override Accurate host")] = None,
74
+ version: Annotated[
75
+ bool,
76
+ typer.Option("--version", "-V", callback=version_callback, is_eager=True, help="Show version"),
77
+ ] = False,
78
+ ) -> None:
79
+ """Kodemeio Accurate Online CLI."""
80
+ ctx.ensure_object(dict)
81
+ ctx.obj = AppContext(
82
+ json_mode=json_output,
83
+ quiet=quiet,
84
+ profile=profile,
85
+ api_token_override=api_token,
86
+ signature_secret_override=signature_secret,
87
+ db_id_override=db_id,
88
+ host_override=host,
89
+ )
90
+ notify_if_outdated(ctx.obj.output, "kctl-accurate", __version__)
91
+
92
+
93
+ def _run() -> None:
94
+ """Entry point with error handling."""
95
+ try:
96
+ app()
97
+ except KctlError as e:
98
+ handle_cli_error(e)
99
+
100
+
101
+ if __name__ == "__main__":
102
+ _run()
@@ -0,0 +1 @@
1
+ """kctl-accurate command groups."""
@@ -0,0 +1,58 @@
1
+ """kctl-accurate auth — Accurate Online auth ops."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+
7
+ import typer
8
+
9
+ from kctl_accurate.core.callbacks import AppContext
10
+
11
+ app = typer.Typer(help="Accurate auth operations: token-info, refresh, logout.")
12
+
13
+
14
+ @app.command("token-info")
15
+ def token_info(ctx: typer.Context) -> None:
16
+ """Show current API token info: user, database, host."""
17
+ actx: AppContext = ctx.obj
18
+ out = actx.output
19
+ info = actx.client.token_info()
20
+
21
+ if actx.json_mode:
22
+ print(json.dumps(info, indent=2, ensure_ascii=False))
23
+ return
24
+
25
+ d = info.get("d", {})
26
+ user = d.get("user") or {}
27
+ db = d.get("database") or {}
28
+
29
+ out.header("Accurate Token Info")
30
+ out.kv("User", user.get("name", "[dim]—[/dim]"))
31
+ out.kv("Email", user.get("email", "[dim]—[/dim]"))
32
+ out.kv("DB ID", str(db.get("id", "[dim]—[/dim]")))
33
+ out.kv("DB Alias", db.get("alias", "[dim]—[/dim]"))
34
+ out.kv("Host", db.get("host", "[dim]—[/dim]"))
35
+
36
+
37
+ @app.command()
38
+ def refresh(ctx: typer.Context) -> None:
39
+ """Refresh the current API session token."""
40
+ actx: AppContext = ctx.obj
41
+ out = actx.output
42
+ result = actx.client.refresh_token()
43
+ if actx.json_mode:
44
+ print(json.dumps(result, indent=2, ensure_ascii=False))
45
+ return
46
+ out.success("Token refreshed")
47
+
48
+
49
+ @app.command()
50
+ def logout(ctx: typer.Context) -> None:
51
+ """Invalidate the current API session."""
52
+ actx: AppContext = ctx.obj
53
+ out = actx.output
54
+ result = actx.client.logout()
55
+ if actx.json_mode:
56
+ print(json.dumps(result, indent=2, ensure_ascii=False))
57
+ return
58
+ out.success("Logged out")