Skip to content

Commit ca69b3a

Browse files
authored
velt-py-v0.1.14 (#252)
1 parent a3b7e20 commit ca69b3a

4 files changed

Lines changed: 342 additions & 0 deletions

File tree

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# Release Update Plan for velt-py v0.1.14
2+
3+
## Overview
4+
- Release Type: Minor (additive)
5+
- Key Changes: Two self-hosting features — (1) `verifyToken` resolver-auth helper (`resolver_auth` config + `VerifyTokenResult` + `ResolverAuthService`, opt-in `velt-py[auth]` extra); (2) comment-resolver save extensions (`SaveCommentResolverRequest.targetComment`, widened `event`, new 14-member `CommentResolverSaveEvent` enum).
6+
- Breaking Changes: No. All additive; existing payloads parse byte-identically. REST API unchanged.
7+
- Target file (ALL edits): `/Users/yoenzhang/Downloads/docs/backend-sdks/python.mdx` (Python SDK convention: dataclasses documented INLINE in its `## Data Models` section, not the shared reference).
8+
9+
## Scope Guardrails (read first)
10+
- **`api-reference/sdk/models/data-models.mdx` is OUT OF SCOPE.** Python dataclasses never go there. The shared `SaveCommentResolverRequest` (lines 532, 9356) and `CommentResolverSaveEvent` there belong to a SEPARATE unmerged Node SDK branch; editing them here causes merge conflicts and violates the Python convention.
11+
- **Agent-4 (wireframes): N/A.** Backend-only release, no UI.
12+
- **Agent-5 (primitives): N/A.** Backend-only release, no UI.
13+
- **Upgrade guide: N/A.** No breaking changes.
14+
- Changelog (`release-notes/version-5/velt-py-changelog.mdx`) already done by Agent-1: v0.1.14 block at lines 9-17, three separate items, each `[Learn more →]` links to bare `/backend-sdks/python` (no anchors). Do not modify.
15+
16+
## Areas Requiring Updates
17+
18+
### 1. Installation — `velt-py[auth]` extra note (Priority: Medium)
19+
- File: `/Users/yoenzhang/Downloads/docs/backend-sdks/python.mdx`
20+
- Insertion point: `### Requirements` (line 29), append after the existing `requests` bullet (line 34).
21+
- Change: Add one bullet — optional `velt-py[auth]` extra installs PyJWT>=2.8.0 and cryptography>=42.0.0, required ONLY for the built-in JWT/JWKS verifier path of `verifyToken`. Custom-callback path and all non-auth features need no new dependency. Install: `pip install 'velt-py[auth]'`.
22+
23+
### 2. Self-Hosting Configuration — `Resolver Auth` tab (Priority: High)
24+
- File: `/Users/yoenzhang/Downloads/docs/backend-sdks/python.mdx`
25+
- Insertion point: inside the `<Tabs>` block at `### Self-Hosting Configuration` (line 123), as a new `<Tab title="Resolver Auth">` placed before `<Tab title="Complete Example">` (line 197).
26+
- Change: Document the `resolver_auth` config block passed to `VeltSDK.initialize`. Show both shapes in one python block:
27+
- `jwt` sub-block: `secret` (HS*) OR `public_key` (PEM, RS*/ES*) OR `jwks_url` (HTTPS JWKS); `algorithms` (REQUIRED allowlist, e.g. `['HS256']`); optional `issuer`, `audience` (enforced when set), `leeway` (seconds), `require` (e.g. `['exp']`).
28+
- `verify` escape hatch: `lambda token, headers: my_decode(token)` returning claims dict or None; takes priority over `jwt`.
29+
- Optional `header` (default `Authorization`), `scheme` (default `Bearer`).
30+
31+
### 3. Self-Hosting Backend — new `### Resolver Token Verification` section (Priority: High)
32+
- File: `/Users/yoenzhang/Downloads/docs/backend-sdks/python.mdx`
33+
- Insertion point: between `### Token` (ends at the getToken Note, line 665) and `### Framework Examples` (line 667). New top-level `###` section under `## Self-Hosting Backend`.
34+
- Change: Document `sdk.selfHosting.verifyToken(headers=None, token=None, **overrides) -> VerifyTokenResult`. Contents in this order (mirror existing Method → note → example pattern):
35+
1. Intro: opt-in via `resolver_auth`; framework-agnostic; fail-closed; authenticates ONLY (resolver services keep their own apiKey/organizationId scoping; helper never consults apiKey/organizationId/resolver DB).
36+
2. Config recap: one-line pointer back to the `Resolver Auth` config tab (area 2).
37+
3. Usage example (Flask/Django-style): `result = sdk.selfHosting.verifyToken(headers=request.headers)`; branch on `result.verified`; return 401 with `result.errorCode` when False; read `result.claims` when True. Also show `token='<raw_jwt>'` direct-pass variant.
38+
4. `VerifyTokenResult` field table — link to the inline `### \`VerifyTokenResult\`` Data Models entry (area 4a).
39+
5. The 9 `errorCode` values: MISSING_TOKEN, EXPIRED, INVALID_SIGNATURE, CLAIM_MISMATCH, ALGORITHM_NOT_ALLOWED, KEY_RESOLUTION_FAILED, VERIFICATION_FAILED, NOT_CONFIGURED, DEPENDENCY_MISSING.
40+
6. Security properties: fail-closed; algorithm pinning (allowlist always required; `alg=none` rejected unconditionally; mixed symmetric+asymmetric allowlists rejected — HS/RS confusion); HTTPS-only JWKS (https:// required; redirect downgrade https→http rejected; 3xx rejected; cache keyed by `(url, kid)`); no credential leakage (token/secret/claims never in error strings or logs); authentication only.
41+
7. Token extraction: from configured header (default `Authorization`, case-insensitive) stripping configured scheme (default `Bearer`); or pass `token=`. Missing/empty/wrong-scheme → `MISSING_TOKEN`.
42+
8. Key resolution: `jwt.secret` → symmetric HS256/384/512 (PEM string in `secret` REJECTED — prevents PEM-as-HMAC forgery); `jwt.public_key` → static RSA/EC for RS*/ES*; `jwt.jwks_url` → HTTPS fetch, cached by `(url, kid)`; fetch failure / non-2xx / unresolvable kid → `KEY_RESOLUTION_FAILED` without raising.
43+
9. Per-call overrides: `**overrides` kwargs merge over configured `resolver_auth` (one-off `jwt`/`verify`/`header`/`scheme`).
44+
10. NOT_CONFIGURED behavior: when `resolver_auth` not configured, returns `verified=False`, `errorCode='NOT_CONFIGURED'` (does not raise, does not silently pass).
45+
11. `ResolverAuthService` export note: newly in `velt_py.services.self_hosting` `__all__`; DB-free service backing `verifyToken`; direct use optional.
46+
47+
### 4a. Data Models (inline) — `### \`VerifyTokenResult\`` dataclass (Priority: High)
48+
- File: `/Users/yoenzhang/Downloads/docs/backend-sdks/python.mdx`
49+
- Insertion point: in `## Data Models` (line 4933), after `### UNSET Sentinel` (line 5019) / before `### \`BaseMetadata\`` (line 5040), OR appended after `### \`BaseMetadata\`` (line 5058). Recommend appending the three new entries (4a, 4b, 4c) after `BaseMetadata`, before `## Resources` (line 5060), to keep the existing comment/reaction cluster intact.
50+
- Change: Follow existing pattern (`### \`Name\``, description w/ version note, ```python @dataclass``` block, **Field notes**). Module: `velt_py.models.resolver_auth`; exported from `velt_py` and `velt_py.models`.
51+
- Fields: `verified: bool`; `claims: Optional[Dict]`; `error: Optional[str]`; `errorCode: Optional[str]`.
52+
- Field notes: `verified` True only when token present & fully verified, or custom callback returned non-None. `claims` decoded payload when verified else None. `error` generic, code-based — never contains token/secret. `errorCode` one of the 9 values (list them).
53+
54+
### 4b. Data Models (inline) — `### \`CommentResolverSaveEvent\`` enum (Priority: High)
55+
- File: `/Users/yoenzhang/Downloads/docs/backend-sdks/python.mdx`
56+
- Insertion point: in `## Data Models`, immediately after the `VerifyTokenResult` entry (4a).
57+
- Change: `CommentResolverSaveEvent(str, Enum)`, exported from `velt_py` and `velt_py.models`; wire values byte-identical to upstream frontend enum. Include a 14-member table (member → wire value):
58+
- STATUS_CHANGE → `comment_annotation.status_change`
59+
- PRIORITY_CHANGE → `comment_annotation.priority_change`
60+
- ASSIGN → `comment_annotation.assign`
61+
- ACCESS_MODE_CHANGE → `comment_annotation.access_mode_change`
62+
- CUSTOM_LIST_CHANGE → `comment_annotation.custom_list_change`
63+
- APPROVE → `comment_annotation.approve`
64+
- ACCEPT → `comment.accept`
65+
- REJECT → `comment.reject`
66+
- SUGGESTION_ACCEPT → `comment_annotation.suggestion_accept`
67+
- SUGGESTION_REJECT → `comment_annotation.suggestion_reject`
68+
- REACTION_ADD → `comment.reaction_add`
69+
- REACTION_DELETE → `comment.reaction_delete`
70+
- SUBSCRIBE → `comment_annotation.subscribe`
71+
- UNSUBSCRIBE → `comment_annotation.unsubscribe`
72+
- Notes to include: parse order in `SaveCommentResolverRequest.from_dict` (ResolverActions FIRST → CommentResolverSaveEvent → raw string fallback for unknown future values); dual export. **CRITICAL preserve verbatim:** `CommentResolverSaveEvent.REACTION_ADD` wire value `comment.reaction_add` is DISTINCT from `ResolverActions.REACTION_ADD` (`reaction.add`, the reaction-resolver action); parse order routes each correctly.
73+
74+
### 4c. Data Models (inline) — `### \`SaveCommentResolverRequest\`` focused entry (Priority: High)
75+
- File: `/Users/yoenzhang/Downloads/docs/backend-sdks/python.mdx`
76+
- Decision: **Add a focused inline `### \`SaveCommentResolverRequest\`` entry** documenting ONLY the v0.1.14 additions (do NOT re-document the whole type). Reason: keeps the `#### saveComments` method note short, gives a stable in-page anchor, and avoids touching the shared `data-models.mdx`. The widened-`event` parse order naturally references the `CommentResolverSaveEvent` entry (4b) directly above it.
77+
- Insertion point: in `## Data Models`, immediately after the `CommentResolverSaveEvent` entry (4b).
78+
- Change: Description with version note (**New in v0.1.14**, additive — existing payloads parse byte-identically). Document:
79+
- `targetComment: Optional[PartialComment]` — the comment the action occurred on, resolved by frontend from `commentId`. `from_dict` parses a `targetComment` dict into `PartialComment`, fail-open (malformed/partial dict never raises). `to_dict` emits `targetComment` only when not None. `saveComments` NEVER persists it (request context only).
80+
- `event` widened to `Optional[Union[ResolverActions, CommentResolverSaveEvent, str]]`. Parse order: ResolverActions FIRST (preserves every existing value), then `CommentResolverSaveEvent`, then raw string for unknown future values.
81+
82+
### 5. `#### saveComments` method note (Priority: Medium)
83+
- File: `/Users/yoenzhang/Downloads/docs/backend-sdks/python.mdx`
84+
- Insertion point: `#### \`saveComments\`` (line 287). Add an additive note after the Response block (line 307), before `#### \`deleteComment\`` (line 309).
85+
- Params link decision: **Keep the existing Params link to `/api-reference/sdk/models/data-models#savecommentresolverrequest` (line 290) as-is** (it documents the full shared shape) AND add one sentence pointing to the new inline `### \`SaveCommentResolverRequest\`` entry (4c) for the v0.1.14 additions. Do not edit `data-models.mdx`.
86+
- Change wording: brief note — "As of v0.1.14, `SaveCommentResolverRequest` adds optional `targetComment` (request context only; never persisted) and a widened `event` accepting `CommentResolverSaveEvent`. See [`SaveCommentResolverRequest`](#savecommentresolverrequest) below." Anchor must match the inline heading from 4c.
87+
88+
## Implementation Sequence (for Agent-3)
89+
1. Area 4a/4b/4c: add the three inline Data Models entries first (anchors must exist before method note links them). Effort: medium.
90+
2. Area 3: add `### Resolver Token Verification` section (links to 4a). Effort: high.
91+
3. Area 2: add `Resolver Auth` config tab. Effort: medium.
92+
4. Area 5: add `saveComments` note linking to 4c anchor. Effort: low.
93+
5. Area 1: add `velt-py[auth]` Requirements bullet. Effort: low.
94+
95+
## Notes for Agent-6 / Agent-7
96+
- Terminology to keep EXACT (do not rephrase/case-fold): `verifyToken`, `resolver_auth`, `CommentResolverSaveEvent`, `SaveCommentResolverRequest`, `targetComment`, `VerifyTokenResult`, `ResolverAuthService`, `velt-py[auth]`.
97+
- The 9 errorCode strings EXACT: MISSING_TOKEN, EXPIRED, INVALID_SIGNATURE, CLAIM_MISMATCH, ALGORITHM_NOT_ALLOWED, KEY_RESOLUTION_FAILED, VERIFICATION_FAILED, NOT_CONFIGURED, DEPENDENCY_MISSING.
98+
- Counts to verify: 14 `CommentResolverSaveEvent` members; 9 errorCode values.
99+
- WATCH wire-value distinctness: `CommentResolverSaveEvent.REACTION_ADD` = `comment.reaction_add` vs `ResolverActions.REACTION_ADD` = `reaction.add`. Never collapse these.
100+
- No anchor changes in `velt-py-changelog.mdx`; its `[Learn more →]` links stay bare `/backend-sdks/python`.
101+
102+
## Quality Checklist
103+
- [ ] All three new inline Data Models entries added to `python.mdx` `## Data Models` (`VerifyTokenResult`, `CommentResolverSaveEvent`, `SaveCommentResolverRequest`) — NOT to `data-models.mdx`.
104+
- [ ] `verifyToken` documented under `## Self-Hosting Backend` (between Token and Framework Examples).
105+
- [ ] `Resolver Auth` config tab + `velt-py[auth]` install note added.
106+
- [ ] `saveComments` additive note added; Params link unchanged; new inline anchor link valid.
107+
- [ ] 14 enum members and 9 errorCodes present and counted.
108+
- [ ] REACTION_ADD wire-value distinctness preserved verbatim.
109+
- [ ] No edits to `api-reference/sdk/models/data-models.mdx`; no wireframe/primitive/upgrade-guide changes.
110+
- [ ] Log written to `/Users/yoenzhang/Downloads/docs/.claude/logs/agent-2-planning-velt-py-0.1.14.md`.
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
## QA Summary for Python SDK (velt-py) v0.1.14
2+
3+
Scope: final QA on the velt-py v0.1.14 docs release. All findings verified via Read/Grep/sed — no answers from memory.
4+
5+
### Per-check results
6+
7+
**Check 1 — `CommentResolverSaveEvent` table — PASS**
8+
Exactly **14** members (table rows 5188–5201 of `backend-sdks/python.mdx`). Wire values match the required set byte-for-byte, in order: comment_annotation.status_change, comment_annotation.priority_change, comment_annotation.assign, comment_annotation.access_mode_change, comment_annotation.custom_list_change, comment_annotation.approve, comment.accept, comment.reject, comment_annotation.suggestion_accept, comment_annotation.suggestion_reject, comment.reaction_add, comment.reaction_delete, comment_annotation.subscribe, comment_annotation.unsubscribe.
9+
10+
**Check 2 — error-code set (9) agreement — PASS**
11+
`diff` of the two locations returned **MATCH** (no drift). Both lists are exactly: MISSING_TOKEN, EXPIRED, INVALID_SIGNATURE, CLAIM_MISMATCH, ALGORITHM_NOT_ALLOWED, KEY_RESOLUTION_FAILED, VERIFICATION_FAILED, NOT_CONFIGURED, DEPENDENCY_MISSING.
12+
- `VerifyTokenResult.errorCode` field-note: line 5175.
13+
- Resolver-Token-Verification error table: lines 722–730.
14+
15+
**Check 3 — distinctness + parse-order notes — PASS**
16+
- Distinctness (line 5205): `CommentResolverSaveEvent.REACTION_ADD` (`comment.reaction_add`) vs `ResolverActions.REACTION_ADD` (`reaction.add`) — present and correct.
17+
- Parse order (line 5203, echoed 5223): ResolverActions first → CommentResolverSaveEvent → raw string — present and correct.
18+
19+
**Check 4 — in-page anchor integrity — PASS**
20+
21+
| Anchor | Headings resolving | Result |
22+
|--------|--------------------|--------|
23+
| `#resolver-token-verification` | 1 (L697) | OK |
24+
| `#verifytokenresult` | 1 (L5155) | OK |
25+
| `#commentresolversaveevent` | 1 (L5177) | OK |
26+
| `#savecommentresolverrequest` | 1 (L5207) | OK — no slug collision |
27+
| `#self-hosting-configuration` | 1 (L122) | OK |
28+
29+
In-page `[`SaveCommentResolverRequest`](#savecommentresolverrequest)` (L337) targets the python.mdx heading. The `#### saveComments` Params link (L318) points to `/api-reference/sdk/models/data-models#savecommentresolverrequest` — different page, correct.
30+
31+
**Check 5 — terminology case-exactness — PASS**
32+
No wrong-case variants found (`verify_token`/`VerifyToken` standalone: none; `resolverAuth`: none). All required exact tokens present: `verifyToken` (8), `resolver_auth` (10), `CommentResolverSaveEvent` (11), `SaveCommentResolverRequest` (13), `targetComment` (5), `VerifyTokenResult` (8), `ResolverAuthService` (2), `velt-py[auth]` (6). snake_case keys (`resolver_auth`/`public_key`/`jwks_url`) and camelCase `errorCode` left as-is (intentional, not drift).
33+
34+
**Check 6 — escaped pipes / table sanity — PASS**
35+
No `\|` inside any ```python``` fence (awk scan empty). No escaped pipes anywhere in the two files. New-table pipe counts consistent: event table = 3/row, error table = 3/row, UNSET table = 4/row (header/separator/rows aligned). `RS\*`/`ES\*` at L738–740 are escaped asterisks in prose, not table pipes — fine.
36+
37+
**Check 7 — changelog — PASS**
38+
Order newest-first: v0.1.14 (L9) sits above v0.1.12 (L21). v0.1.14 block has **3** separate `[**Self Hosting**]` bullets (not merged). Date `description="June 19, 2026"`. All 3 links are bare `(/backend-sdks/python)`.
39+
40+
**Check 8 — scope guard — PASS**
41+
`git diff --name-only`:
42+
```
43+
backend-sdks/python.mdx
44+
release-notes/version-5/velt-py-changelog.mdx
45+
```
46+
Forbidden files all untouched: `api-reference/sdk/models/data-models.mdx`, `release-notes/version-5/velt-node-changelog.mdx`, `backend-sdks/node.mdx`, `self-host-data/*`. (Node v1.0.7 correctly absent — lives on its own branch.) The only other working-tree entry is the untracked planning artifact `.claude/logs/agent-2-planning-velt-py-0.1.14.md`, not a doc edit.
47+
48+
### Fixes applied
49+
None. All 8 checks passed on first review; no safe/justified edit was warranted.
50+
51+
### Counts confirmed
52+
- `CommentResolverSaveEvent` members: **14**
53+
- `errorCode` set: **9** (field-note ↔ table: MATCH)
54+
55+
Issues found: 0

0 commit comments

Comments
 (0)