@elixpo/lixblogs-cli 1.1.2 → 1.3.3

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,35 @@ 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
+ # Credentials are saved under the authenticated username and made active.
33
+
34
+ # Save credentials under an explicit local profile name
35
+ node bin/lixblogs.mjs login --profile personal
33
36
 
34
37
  # Check login status
35
- node bin/lixblogs.mjs auth status
38
+ node bin/lixblogs.mjs whoami
36
39
 
37
40
  # List profiles and choose the active one
38
- node bin/lixblogs.mjs auth profiles
39
- node bin/lixblogs.mjs auth use work
41
+ node bin/lixblogs.mjs profiles
42
+ node bin/lixblogs.mjs use work
40
43
 
41
44
  # Log out (clears local credentials only)
42
- node bin/lixblogs.mjs auth logout
45
+ node bin/lixblogs.mjs logout
43
46
 
44
47
  # Revoke the token server-side and clear local credentials (destructive)
45
48
  node bin/lixblogs.mjs auth revoke --yes
46
49
  ```
47
50
 
51
+ Interactive login shows one compact device card and stays quiet while Accounts
52
+ approval is pending. Press Enter to open the verification URL locally, use
53
+ `--open` to open it immediately, or copy the URL to any browser when connected
54
+ to a VPS. Device authorization does not require a localhost callback or an
55
+ exposed port. The authenticated username becomes the local profile alias unless
56
+ `--profile` explicitly overrides it. Run `lixblogs login` again to add another
57
+ account, `lixblogs profiles` to list saved accounts, and
58
+ `lixblogs use <username>` to switch the active one.
59
+
48
60
  ### Blog lifecycle
49
61
 
50
62
  Request the permissions needed for the operations you intend to use:
@@ -63,13 +75,72 @@ lixblogs blog list --status draft
63
75
  lixblogs blog create --file post.md --title "A new post" --tag engineering
64
76
  lixblogs blog get <id> --json
65
77
  lixblogs blog edit <id> --editor
66
- lixblogs blog publish <id>
67
- lixblogs blog unpublish <id>
78
+ lixblogs blog publish <id> --yes
79
+ lixblogs blog unpublish <id> --yes
68
80
  lixblogs blog delete <id> --yes
69
81
  lixblogs blog list --status trashed
70
- lixblogs blog restore <id>
82
+ lixblogs blog restore <id> --yes
83
+ ```
84
+
85
+ Inspect valid publication targets before assigning organization metadata:
86
+
87
+ ```bash
88
+ lixblogs org list
89
+ lixblogs org get ORG_ID
90
+ lixblogs org collections ORG_ID
91
+ lixblogs org members ORG_ID
92
+ lixblogs org targets --json
93
+ ```
94
+
95
+ Organization lookup is membership-bound. A slug alone never grants access;
96
+ the API resolves the authenticated user's role before returning tenant data.
97
+
98
+ Editorial collaboration stays separate from publishing:
99
+
100
+ ```bash
101
+ lixblogs collab invitations
102
+ lixblogs collab list BLOG_ID
103
+ lixblogs collab invite BLOG_ID --user reviewer --role viewer --yes
104
+ lixblogs collab role BLOG_ID --user reviewer --role editor --yes
105
+ lixblogs collab accept BLOG_ID --yes
106
+ lixblogs collab decline BLOG_ID --yes
107
+ ```
108
+
109
+ Viewer, editor, and admin roles grant different editorial authority. None of
110
+ these commands publishes a post; public-state changes still use `blog publish`
111
+ with the publish scope and a separate confirmation.
112
+
113
+ ### Creator analytics
114
+
115
+ Analytics is read-only and uses bounded date ranges and dimensions:
116
+
117
+ ```bash
118
+ lixblogs login --scope openid --scope profile --scope lixblogs:analytics:read
119
+ lixblogs analytics query --range 30d --dimension overview --json --no-input
120
+ lixblogs analytics query --scope org:ORG_ID --range custom \
121
+ --from 2026-07-01 --to 2026-07-31 --dimension posts --limit 25 --json --no-input
122
+ lixblogs analytics export --dimension timeline --format csv --output analytics.csv
123
+ ```
124
+
125
+ Organization analytics also requires `lixblogs:organizations:read`. Results contain
126
+ aggregates only; the API does not expose visitor identifiers or credentials.
127
+ Exports refuse to overwrite an existing file.
128
+
129
+ ### Agent skills
130
+
131
+ The npm artifact bundles each skill independently:
132
+
133
+ ```bash
134
+ lixblogs skill list
135
+ lixblogs skill inspect lixblogs-author
136
+ lixblogs skill install lixblogs-author --target .agents/skills --dry-run
137
+ lixblogs skill install lixblogs-author --target .agents/skills --yes
71
138
  ```
72
139
 
140
+ Install only the skill needed by the current agent. Existing files are not
141
+ replaced unless `--force --yes` is explicit. The bundled skill declares its
142
+ minimum compatible CLI version and scopes.
143
+
73
144
  `create`, `edit`, `publish`, `unpublish`, `delete`, and `restore` accept
74
145
  `--dry-run`. Content input is mutually exclusive: `--file`, `--stdin`,
75
146
  `--content`, or `--editor`. Permanent deletion additionally requires
@@ -80,7 +151,7 @@ command exits with code 3 and retains both versions under
80
151
  `.lixblogs-conflicts/`; it never overwrites the newer server revision.
81
152
 
82
153
  Global flags:
83
- - `--profile <name>` — named profile to use (default: `"default"`)
154
+ - `--profile <name>` — override the username-based local account alias
84
155
  - `--env <environment>` — override environment (`development` | `staging` | `production`)
85
156
  - `--scope <scope>` — request an additional/alternate OAuth scope; repeatable
86
157
  - `--open` — open the verification URL with the device code pre-filled
@@ -89,7 +160,7 @@ Global flags:
89
160
  `https://blogs.elixpo.com`
90
161
  - `--json` — machine-readable JSON output
91
162
  - `--quiet` — suppress non-essential output
92
- - `--yes`, `-y` — auto-confirm destructive actions (required for `revoke`)
163
+ - `--yes`, `-y` — confirm publishing and destructive state changes
93
164
  - `--allow-insecure-fallback` — explicit opt-in: if the OS keychain is
94
165
  unavailable, use a non-persistent in-memory store instead of failing
95
166
 
@@ -103,10 +174,34 @@ Global flags:
103
174
  environment, for example `--env development --auth-provider mock`.
104
175
  - The resource contract, scopes, pagination, errors, and mutation guarantees
105
176
  are documented in [API.md](API.md).
177
+ - Release compatibility, provenance, smoke gates, and rollback are documented
178
+ in [RELEASE.md](RELEASE.md). Contract changes are summarized in
179
+ [CHANGELOG.md](CHANGELOG.md).
106
180
 
107
181
  The production client is public and has no client secret. Never add one to
108
182
  CLI configuration, package files, or GitHub secrets.
109
183
 
184
+ ### Configuration precedence
185
+
186
+ Configuration resolves in this order: command flags, `LIXBLOGS_*` environment
187
+ variables, the selected named profile, then production-safe defaults. Use
188
+ `lixblogs whoami --json --no-input` to verify the active profile, environment,
189
+ granted scopes, and expiry before automation. Flags are best for one command;
190
+ environment values are best for a contained CI job. Credentials remain in the
191
+ OS keychain and are never read from environment variables.
192
+
193
+ ### Troubleshooting
194
+
195
+ - `invalid_scope`: Accounts has not registered the requested permission for
196
+ this client; do not substitute a broader token.
197
+ - `insufficient_scope`: log in again with only the reported missing scope.
198
+ - `account_not_provisioned`: sign in to LixBlogs once with the same Accounts
199
+ identity before retrying the CLI.
200
+ - `precondition_failed`: fetch the current post, reconcile the retained
201
+ conflict copy, and retry with the new revision.
202
+ - `rate_limit_exceeded`: honor `Retry-After`; do not fan out retries.
203
+ - Include the returned request ID in a report, never a token or credential.
204
+
110
205
  ## Development
111
206
 
112
207
  ```bash
@@ -146,10 +241,8 @@ tests.
146
241
  See [#135](https://github.com/elixpo/blogs.elixpo/issues/135) for the full
147
242
  scope. Rough remaining order:
148
243
 
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
244
+ 1. Media commands
245
+ 2. Interactive terminal UI and branding in a separate issue
153
246
 
154
247
  ## Contributing
155
248
 
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.