@elixpo/lixblogs-cli 1.1.2 → 1.3.1

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/API.md CHANGED
@@ -20,6 +20,7 @@ logged by the resource API.
20
20
  | Method | Path | Scope | Behavior |
21
21
  | --- | --- | --- | --- |
22
22
  | `GET` | `/api/v1` | public | API and compatibility metadata |
23
+ | `GET` | `/api/v1/me` | `lixblogs:profile:read` | Current LixBlogs identity |
23
24
  | `GET` | `/api/v1/blogs` | `lixblogs:blog:read` | Accessible blog metadata |
24
25
  | `GET` | `/api/v1/blogs/{id}` | `lixblogs:blog:read` | One accessible blog and its content |
25
26
  | `POST` | `/api/v1/blogs` | `lixblogs:blog:write` | Create a draft |
@@ -28,6 +29,23 @@ logged by the resource API.
28
29
  | `POST` | `/api/v1/blogs/{id}/unpublish` | `lixblogs:blog:publish` | Return a post to draft |
29
30
  | `DELETE` | `/api/v1/blogs/{id}` | `lixblogs:blog:delete` | Move a post to trash |
30
31
  | `POST` | `/api/v1/blogs/{id}/restore` | `lixblogs:blog:delete` | Restore a trashed post |
32
+ | `GET` | `/api/v1/orgs` | `lixblogs:organizations:read` | Organizations the caller belongs to |
33
+ | `GET` | `/api/v1/orgs/{id}` | `lixblogs:organizations:read` | One caller-visible organization and role |
34
+ | `GET` | `/api/v1/orgs/{id}/collections` | `lixblogs:organizations:read` | Collections within a caller membership |
35
+ | `GET` | `/api/v1/orgs/{id}/members` | `lixblogs:organizations:read` | Members and roles within a caller membership |
36
+ | `GET` | `/api/v1/blogs/{id}/collaborators` | `lixblogs:collaboration:read` | Editorial team and effective role |
37
+ | `POST` | `/api/v1/blogs/{id}/collaborators` | `lixblogs:collaboration:write` | Invite or reassign a collaborator |
38
+ | `PATCH` | `/api/v1/blogs/{id}/collaborators` | `lixblogs:collaboration:write` | Change a collaborator role |
39
+ | `DELETE` | `/api/v1/blogs/{id}/collaborators` | `lixblogs:collaboration:write` | Remove a collaborator or leave a team |
40
+ | `GET` | `/api/v1/collaboration/invitations` | `lixblogs:collaboration:read` | Current identity's invitations |
41
+ | `POST` | `/api/v1/collaboration/invitations` | `lixblogs:collaboration:write` | Accept or decline an invitation |
42
+ | `GET` | `/api/v1/analytics` | `lixblogs:analytics:read` | Bounded creator analytics dimensions |
43
+
44
+ `GET /api/v1/analytics` accepts `scope=personal|org:<id>`, `range=7d|30d|90d|12m|custom`,
45
+ `from`, `to`, `dimension=overview|timeline|posts|sources|devices|countries`, `limit=1..100`,
46
+ and an opaque `cursor`. Organization queries additionally require `lixblogs:organizations:read`
47
+ and an owner, admin, or maintain membership. Responses contain aggregate creator data;
48
+ visitor identifiers are never returned.
31
49
 
32
50
  `GET /api/v1/blogs` accepts `status=all|draft|published`, `limit=1..100`, and
33
51
  an opaque `cursor`. Results include authored blogs, accepted collaborations,
package/CHANGELOG.md ADDED
@@ -0,0 +1,10 @@
1
+ # Changelog
2
+
3
+ Release notes are generated from merged pull requests. This file records contract-level changes that users must see before upgrading.
4
+
5
+ ## 1.3.0
6
+
7
+ - Added scoped organization and editorial commands.
8
+ - Added bounded, read-only creator analytics with JSON and CSV export.
9
+ - Bundled five independently installable LixBlogs agent skills.
10
+ - Added packed-artifact, Accounts device-flow, Blogs resource-contract, provenance, and rollback release gates.
package/README.md CHANGED
@@ -3,9 +3,9 @@
3
3
  The official CLI for LixBlogs — publish, manage, and inspect blogs through
4
4
  the supported API. Built for creators and agent/automation use.
5
5
 
6
- **Status: initial release.** This package implements production device-flow
7
- authentication and the core blog lifecycle over the stable LixBlogs API v1
8
- contract. The interactive terminal UI is intentionally a separate follow-up.
6
+ This package implements production device-flow authentication and the core
7
+ blog lifecycle over the stable LixBlogs API v1 contract. Its output stays
8
+ compact and predictable for both terminals and automation.
9
9
 
10
10
  ## Install (local development)
11
11
 
@@ -14,7 +14,6 @@ cd packages/lixblogs-cli
14
14
  npm install
15
15
  ```
16
16
 
17
- There's no published npm release yet. Once available, install will be:
18
17
  ```bash
19
18
  npm install -g @elixpo/lixblogs-cli
20
19
  ```
@@ -29,22 +28,32 @@ node bin/lixblogs.mjs --help
29
28
 
30
29
  ```bash
31
30
  # Log in via device authorization
32
- node bin/lixblogs.mjs auth login
31
+ node bin/lixblogs.mjs login
32
+
33
+ # Save credentials under an explicit local profile name
34
+ node bin/lixblogs.mjs login --profile personal
33
35
 
34
36
  # Check login status
35
- node bin/lixblogs.mjs auth status
37
+ node bin/lixblogs.mjs whoami
36
38
 
37
39
  # List profiles and choose the active one
38
- node bin/lixblogs.mjs auth profiles
39
- node bin/lixblogs.mjs auth use work
40
+ node bin/lixblogs.mjs profiles
41
+ node bin/lixblogs.mjs use work
40
42
 
41
43
  # Log out (clears local credentials only)
42
- node bin/lixblogs.mjs auth logout
44
+ node bin/lixblogs.mjs logout
43
45
 
44
46
  # Revoke the token server-side and clear local credentials (destructive)
45
47
  node bin/lixblogs.mjs auth revoke --yes
46
48
  ```
47
49
 
50
+ Interactive login shows one compact device card and stays quiet while Accounts
51
+ approval is pending. Press Enter to open the verification URL locally, use
52
+ `--open` to open it immediately, or copy the URL to any browser when connected
53
+ to a VPS. Device authorization does not require a localhost callback or an
54
+ exposed port. Profile names such as `personal`, `work`, or `test` are local
55
+ credential slots; `whoami` reports the actual Accounts identity.
56
+
48
57
  ### Blog lifecycle
49
58
 
50
59
  Request the permissions needed for the operations you intend to use:
@@ -63,13 +72,72 @@ lixblogs blog list --status draft
63
72
  lixblogs blog create --file post.md --title "A new post" --tag engineering
64
73
  lixblogs blog get <id> --json
65
74
  lixblogs blog edit <id> --editor
66
- lixblogs blog publish <id>
67
- lixblogs blog unpublish <id>
75
+ lixblogs blog publish <id> --yes
76
+ lixblogs blog unpublish <id> --yes
68
77
  lixblogs blog delete <id> --yes
69
78
  lixblogs blog list --status trashed
70
- lixblogs blog restore <id>
79
+ lixblogs blog restore <id> --yes
80
+ ```
81
+
82
+ Inspect valid publication targets before assigning organization metadata:
83
+
84
+ ```bash
85
+ lixblogs org list
86
+ lixblogs org get ORG_ID
87
+ lixblogs org collections ORG_ID
88
+ lixblogs org members ORG_ID
89
+ lixblogs org targets --json
90
+ ```
91
+
92
+ Organization lookup is membership-bound. A slug alone never grants access;
93
+ the API resolves the authenticated user's role before returning tenant data.
94
+
95
+ Editorial collaboration stays separate from publishing:
96
+
97
+ ```bash
98
+ lixblogs collab invitations
99
+ lixblogs collab list BLOG_ID
100
+ lixblogs collab invite BLOG_ID --user reviewer --role viewer --yes
101
+ lixblogs collab role BLOG_ID --user reviewer --role editor --yes
102
+ lixblogs collab accept BLOG_ID --yes
103
+ lixblogs collab decline BLOG_ID --yes
104
+ ```
105
+
106
+ Viewer, editor, and admin roles grant different editorial authority. None of
107
+ these commands publishes a post; public-state changes still use `blog publish`
108
+ with the publish scope and a separate confirmation.
109
+
110
+ ### Creator analytics
111
+
112
+ Analytics is read-only and uses bounded date ranges and dimensions:
113
+
114
+ ```bash
115
+ lixblogs login --scope openid --scope profile --scope lixblogs:analytics:read
116
+ lixblogs analytics query --range 30d --dimension overview --json --no-input
117
+ lixblogs analytics query --scope org:ORG_ID --range custom \
118
+ --from 2026-07-01 --to 2026-07-31 --dimension posts --limit 25 --json --no-input
119
+ lixblogs analytics export --dimension timeline --format csv --output analytics.csv
120
+ ```
121
+
122
+ Organization analytics also requires `lixblogs:organizations:read`. Results contain
123
+ aggregates only; the API does not expose visitor identifiers or credentials.
124
+ Exports refuse to overwrite an existing file.
125
+
126
+ ### Agent skills
127
+
128
+ The npm artifact bundles each skill independently:
129
+
130
+ ```bash
131
+ lixblogs skill list
132
+ lixblogs skill inspect lixblogs-author
133
+ lixblogs skill install lixblogs-author --target .agents/skills --dry-run
134
+ lixblogs skill install lixblogs-author --target .agents/skills --yes
71
135
  ```
72
136
 
137
+ Install only the skill needed by the current agent. Existing files are not
138
+ replaced unless `--force --yes` is explicit. The bundled skill declares its
139
+ minimum compatible CLI version and scopes.
140
+
73
141
  `create`, `edit`, `publish`, `unpublish`, `delete`, and `restore` accept
74
142
  `--dry-run`. Content input is mutually exclusive: `--file`, `--stdin`,
75
143
  `--content`, or `--editor`. Permanent deletion additionally requires
@@ -89,7 +157,7 @@ Global flags:
89
157
  `https://blogs.elixpo.com`
90
158
  - `--json` — machine-readable JSON output
91
159
  - `--quiet` — suppress non-essential output
92
- - `--yes`, `-y` — auto-confirm destructive actions (required for `revoke`)
160
+ - `--yes`, `-y` — confirm publishing and destructive state changes
93
161
  - `--allow-insecure-fallback` — explicit opt-in: if the OS keychain is
94
162
  unavailable, use a non-persistent in-memory store instead of failing
95
163
 
@@ -103,10 +171,34 @@ Global flags:
103
171
  environment, for example `--env development --auth-provider mock`.
104
172
  - The resource contract, scopes, pagination, errors, and mutation guarantees
105
173
  are documented in [API.md](API.md).
174
+ - Release compatibility, provenance, smoke gates, and rollback are documented
175
+ in [RELEASE.md](RELEASE.md). Contract changes are summarized in
176
+ [CHANGELOG.md](CHANGELOG.md).
106
177
 
107
178
  The production client is public and has no client secret. Never add one to
108
179
  CLI configuration, package files, or GitHub secrets.
109
180
 
181
+ ### Configuration precedence
182
+
183
+ Configuration resolves in this order: command flags, `LIXBLOGS_*` environment
184
+ variables, the selected named profile, then production-safe defaults. Use
185
+ `lixblogs whoami --json --no-input` to verify the active profile, environment,
186
+ granted scopes, and expiry before automation. Flags are best for one command;
187
+ environment values are best for a contained CI job. Credentials remain in the
188
+ OS keychain and are never read from environment variables.
189
+
190
+ ### Troubleshooting
191
+
192
+ - `invalid_scope`: Accounts has not registered the requested permission for
193
+ this client; do not substitute a broader token.
194
+ - `insufficient_scope`: log in again with only the reported missing scope.
195
+ - `account_not_provisioned`: sign in to LixBlogs once with the same Accounts
196
+ identity before retrying the CLI.
197
+ - `precondition_failed`: fetch the current post, reconcile the retained
198
+ conflict copy, and retry with the new revision.
199
+ - `rate_limit_exceeded`: honor `Retry-After`; do not fan out retries.
200
+ - Include the returned request ID in a report, never a token or credential.
201
+
110
202
  ## Development
111
203
 
112
204
  ```bash
@@ -146,10 +238,8 @@ tests.
146
238
  See [#135](https://github.com/elixpo/blogs.elixpo/issues/135) for the full
147
239
  scope. Rough remaining order:
148
240
 
149
- 1. Media, organization, and stats commands
150
- 2. Packaging and release automation
151
- 3. Interactive terminal UI and branding in a separate issue
152
- 4. Agent skill packages and cross-repository E2E coverage
241
+ 1. Media commands
242
+ 2. Interactive terminal UI and branding in a separate issue
153
243
 
154
244
  ## Contributing
155
245
 
package/RELEASE.md ADDED
@@ -0,0 +1,30 @@
1
+ # Release and compatibility policy
2
+
3
+ ## Compatibility
4
+
5
+ - CLI `1.x` targets LixBlogs API `/api/v1` and the Accounts OAuth discovery contract.
6
+ - Additive response fields and commands are minor releases. Fixes without contract changes are patch releases.
7
+ - Removing a command, field, scope, or error code requires a CLI major release or API `/api/v2`.
8
+ - The resource metadata `minCliVersion` is authoritative. An older client must stop before authenticated requests and ask the user to upgrade.
9
+ - Node 18 is the supported runtime floor. Release gates run on Node 22.
10
+
11
+ ## Release
12
+
13
+ 1. Update the package version and `CHANGELOG.md` in a reviewed PR.
14
+ 2. Run the manual **LixBlogs CLI release gate**. It tests the package, installs the exact tarball, checks bundled skills, verifies Blogs resource contracts, and runs the Accounts device-flow contract.
15
+ 3. Tag the reviewed commit as `lixblogs-cli-vX.Y.Z`.
16
+ 4. The publish workflow reruns the gate, checks that tag and package versions match, attests the tarball, publishes it through npm trusted publishing with provenance, and creates generated GitHub release notes.
17
+
18
+ No npm token is stored in this workflow. The npm package must configure this repository and `publish-lixblogs-cli.yml` as a trusted publisher.
19
+
20
+ ## Smoke criteria
21
+
22
+ The packed artifact must install into an empty prefix, render `--help`, discover all five scoped skills, and pass auth, blog lifecycle, organization, collaboration, and analytics command tests. Accounts must pass device approval, refresh rotation, replay protection, and revocation. Blogs must pass bearer validation, concurrency/idempotency, analytics, and media request-boundary tests.
23
+
24
+ ## Rollback
25
+
26
+ 1. Stop a broken release with `npm deprecate @elixpo/lixblogs-cli@X.Y.Z "Do not use; upgrade to X.Y.N"`.
27
+ 2. Restore the previous compatible version with `npm dist-tag add @elixpo/lixblogs-cli@GOOD latest`.
28
+ 3. Open a patch PR; never reuse or delete the published version.
29
+ 4. Re-run the release gate and publish a new patch tag.
30
+ 5. If the API contract caused the failure, raise `minCliVersion` only after the compatible patch is available.