@nitida/sdk 0.31.6 → 0.31.7
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/README.md +37 -0
- package/package.json +1 -1
- package/skills/nitida-sdk/SKILL.md +25 -0
package/README.md
CHANGED
|
@@ -1403,6 +1403,43 @@ If you need a dimension that doesn't exist, two options: use the closest
|
|
|
1403
1403
|
preset and let the browser scale, or file an issue to add it to the
|
|
1404
1404
|
server-side pipeline (a platform-wide addition, not a per-tenant one).
|
|
1405
1405
|
|
|
1406
|
+
### ⭐ What happens when two tenants upload the SAME image
|
|
1407
|
+
|
|
1408
|
+
Dedup is **content-addressed and cross-tenant**: the sha is a hash of the bytes,
|
|
1409
|
+
so if you and another customer upload the same logo, the same stock photo or the
|
|
1410
|
+
same placeholder, you share a candidate row. This is normal, not exotic.
|
|
1411
|
+
|
|
1412
|
+
A `/t/…` transform URL names **content**, not a tenant — there is no tenant
|
|
1413
|
+
segment in it. Three consequences follow, and all three are measured behaviour:
|
|
1414
|
+
|
|
1415
|
+
**1 · A signed transform is resolved by the SIGNATURE, not by tenant id.**
|
|
1416
|
+
The signature proves possession of one specific tenant's key, which is exactly
|
|
1417
|
+
the identity the URL lacks. Before `2026-08-25` the lowest tenant id won, so a
|
|
1418
|
+
correctly signed URL could be verified against someone else's key and answer
|
|
1419
|
+
`invalid_signature`. Nothing to do on your side — just know the signature is
|
|
1420
|
+
what disambiguates.
|
|
1421
|
+
|
|
1422
|
+
**2 · `strict_transforms` fails CLOSED across every tenant that shares the sha.**
|
|
1423
|
+
If any tenant holding those bytes requires signed URLs, the unsigned request is
|
|
1424
|
+
refused — because an unsigned request cannot say which tenant it belongs to, and
|
|
1425
|
+
picking the most permissive one would let a third party defeat your policy.
|
|
1426
|
+
|
|
1427
|
+
> ⚠️ The cost, stated plainly: if you do **not** use `strict_transforms` but you
|
|
1428
|
+
> share content with someone who does, that sha needs a signed URL from you too.
|
|
1429
|
+
> The alternative — failing open — means your own strict setting is silently
|
|
1430
|
+
> cancelled by a stranger. A 401 you fix by signing is the cheaper mistake.
|
|
1431
|
+
|
|
1432
|
+
**3 · Making an asset private does NOT unpublish another tenant's public copy.**
|
|
1433
|
+
`visibility: "private"` retracts **your** row. If another tenant uploaded the
|
|
1434
|
+
same bytes and left them public, that copy keeps serving, and a `/t/` request
|
|
1435
|
+
resolves to it. No new information leaks — those exact bytes were already public
|
|
1436
|
+
— but do not read "private" as "these bytes are now unreachable". It means
|
|
1437
|
+
"reachable through me only by signature".
|
|
1438
|
+
|
|
1439
|
+
> If that distinction matters for your content, the answer is not a flag: it is
|
|
1440
|
+
> not to share the bytes. Anything unique to you (a customer photo, a document,
|
|
1441
|
+
> a render) has a unique sha and never collides.
|
|
1442
|
+
|
|
1406
1443
|
### CDN URL format
|
|
1407
1444
|
|
|
1408
1445
|
`<cdnBase>/<tenantId base36>/v/<sha16>-<presetCode>.<ext>`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nitida/sdk",
|
|
3
|
-
"version": "0.31.
|
|
3
|
+
"version": "0.31.7",
|
|
4
4
|
"description": "nitida — the media SDK: browser and mobile upload with resume, client-side compression, on-the-fly transforms behind a CDN, video transcode, HLS ladders and AI proxies. Multi-tenant.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"publishConfig": {
|
|
@@ -501,6 +501,31 @@ The progressive MP4 is capped unconditionally at 1920 wide, so `getAssetUrl(sha,
|
|
|
501
501
|
never exceeds 1080p whatever you uploaded. A rung that weighs *more* than its own source (measured:
|
|
502
502
|
5090 vs 4866 kbps) is the signature of the fallback path, not of a broken ladder.
|
|
503
503
|
|
|
504
|
+
### 3c. ⭐ Dedup is CROSS-TENANT, and three things follow from it
|
|
505
|
+
|
|
506
|
+
The sha hashes the **bytes**, so two customers who upload the same logo, stock
|
|
507
|
+
photo or placeholder share a candidate row. A `/t/…` URL names content and
|
|
508
|
+
carries **no tenant segment**. Measured behaviour as of 2026-08-25:
|
|
509
|
+
|
|
510
|
+
| | |
|
|
511
|
+
|---|---|
|
|
512
|
+
| **signed** `/t/` | the **signature** picks the tenant — it proves possession of one key, which is the identity the URL lacks. (Before this, the lowest tenant id won and a valid signature could answer `invalid_signature`.) |
|
|
513
|
+
| **`strict_transforms`** | fails **closed** across every tenant sharing that sha. If any of them requires signing, the unsigned request is refused. |
|
|
514
|
+
| **`visibility: "private"`** | retracts **your** row only. Another tenant's public copy of the same bytes keeps serving, and `/t/` resolves to it. |
|
|
515
|
+
|
|
516
|
+
⚠️ **Do not read `private` as "these bytes are unreachable".** It means
|
|
517
|
+
"reachable through me only by signature". Nothing new leaks — those bytes were
|
|
518
|
+
already public via the other tenant — but the promise is narrower than it looks.
|
|
519
|
+
|
|
520
|
+
⚠️ And the cost of failing closed, stated plainly: a tenant that does **not**
|
|
521
|
+
use `strict_transforms` but shares content with one that does will need signed
|
|
522
|
+
URLs for that sha. Failing open would let a stranger cancel someone's policy;
|
|
523
|
+
a 401 you fix by signing is the cheaper of the two mistakes.
|
|
524
|
+
|
|
525
|
+
⭐ **Anything unique to you has a unique sha and never collides** — a customer
|
|
526
|
+
photo, a document, a render. Collisions are for generic assets, which is exactly
|
|
527
|
+
the content where sharing costs you nothing.
|
|
528
|
+
|
|
504
529
|
## 4. Resolving a stored reference — `extractAssetSha`
|
|
505
530
|
|
|
506
531
|
When a stored value is already an `8ok.uk` URL, pull its sha:
|