Beş dakikada ilk imza
Komut satırı, Node kütüphanesi, REST API ve MCP sunucusu aynı çekirdeği paylaşır; metin, görsel ve video aynı anahtarlarla imzalanır. Her şey açık formatla doğrulanır; dilediğiniz dilde kendi doğrulayıcınızı yazabilirsiniz.
Hızlı başlangıç
Anahtar üretin, bir dosyayı imzalayın, doğrulayın. Özel anahtar makinenizden çıkmaz. Aynı anahtar metni de medyayı da imzalar.
# kurulum npm install -g @jettymark/cli # yayıncı anahtarı (açık kısmı stdout'a yazar) jettymark keygen --issuer "Ege Haber Ajansı" --out ~/.jettymark/ege.json # metin: her paragraf ayrı blok, abone 17 için kopya jettymark sign --key ~/.jettymark/ege.json --doc-id haber-2026-11-01-42 \ --recipient abone-17 --in haber.txt --out haber-imzali.txt # görsel ya da video: aynı anahtar, aynı belge kimliği mantığı jettymark sign-media --key ~/.jettymark/ege.json --doc-id foto-2026-11-01-7 \ --recipient abone-17 --in foto.jpg --out foto-imzali.jpg # doğrula (yayıncı anahtarı güven listesinde) jettymark trust add-wellknown egehaber.example jettymark verify --in haber-imzali.txt ✅ ORİJİNAL — Ege Haber Ajansı tarafından 01.11.2026 09:12 UTC tarihinde imzalanmış; 3 bloğun tamamı doğrulandı. jettymark verify-media --in foto-imzali.jpg ✅ ORİJİNAL — Ege Haber Ajansı tarafından 01.11.2026 09:12 UTC tarihinde imzalanmış; içerik imzayla uyuşuyor
Node kütüphanesi
Bağımlılığı olmayan çekirdek: kanonikleştirme, taşıyıcı, çerçeve, Ed25519 imza ve doğrulama, rapor biçimlendirme. Medya için aynı paketin /media girişi (Node: sharp + ffmpeg) ve /media-web girişi (tarayıcı: canvas, kamera) vardır.
import { signText, verifyText, generateKeyPair, publicPart, formatReport } from "@jettymark/core"; import { signImage, verifyImage, signVideo, verifyVideo, formatMediaReport } from "@jettymark/core/media"; const key = generateKeyPair("Ege Haber Ajansı"); const { text, docId, blocks } = signText(article, key, { docId: "haber-42", recipient: "abone-17" }); const report = verifyText(text, [publicPart(key)]); report.verdict // "authentic" | "partial" | "modified" | "untrusted" | "damaged" | "unsigned" report.frames // blok başına: durum, belge, kid, zaman, kapsanan kelimeler report.uncovered // imza kapsamı dışındaki metin parçaları formatReport(report, "tr"); // görsel: bytes | yol → imzalı dosya + rapor (güç, marjlar, işaret kimliği) const signed = await signImage("foto.jpg", key, { docId: "foto-7", recipient: "abone-17", strength: 3 }); signed.markId // 16 hex: kayıt defterinin anahtarı const mr = await verifyImage(signed.bytes, [publicPart(key)]); mr.verdict // aynı altı sonuç; mr.reason: "cropped" | "id_only" | … mr.content.cells // 48 bölge (8×6): görünür mü, doygun mu, ton eğrisinden sapma (gri düzey), işaretli mi formatMediaReport(mr, "tr"); // video: dosya yolları, 2 sn'lik parçalar, ffmpeg gerekir await signVideo("klip.mp4", "klip-imzali.mp4", key, { docId: "video-3" }); (await verifyVideo("klip-imzali.mp4", [publicPart(key)])).video // parça parça sonuç
Tarayıcıda import { verifyImageBlob, CameraSession } from "@jettymark/core/media-web": dosya cihazda çözülür, sunucuya yalnızca işaret kimliği ve özet değerler gider.
REST API
Sunucu tarafı imzalama ve kayıt defteri için. Doğrulama uç noktaları anonimdir ve kota gerektirmez; yüklenen dosya hiçbir zaman saklanmaz. Kimlik: Authorization: Bearer tm_live_… (kapsamlı API anahtarı). Tam sözleşme: apps/web/API.md.
| Uç nokta | Açıklama | Kimlik |
|---|---|---|
| POST /api/v1/sign | Metni imzalar, belge kaydı açar, abone listesi verilirse kopya başına döner | API anahtarı |
| POST /api/v1/verify | Metni, bağlantıyı ya da metin dosyasını doğrular; kayıt defteriyle fark görünümü | Anonim |
| GET /api/v1/documents/{id} | Belge (metin, görsel ya da video), versiyonlar, doğrulama günlüğü | API anahtarı |
| POST /api/v1/trace | Sızan metinden abone parmak izini çözer | API anahtarı |
| POST /api/v1/webhooks | Yayın webhook'u: CMS metni gönderir, imzalı metni geri alır | API anahtarı |
Medya: hızlı başlangıç
Görseller (JPEG, PNG, WebP, en az 384 × 256 px, en fazla 50 MB) eşzamanlı imzalanır; videolar (MP4/H.264 (WebM VP9 girişi kabul edilir, çıkış MP4), en fazla 500 MB) bir iş olarak kuyruğa girer ve GET /api/v1/jobs/{id} ile izlenir. HDR, 10 bit, animasyonlu GIF/WebP, CMYK v1'de 415 ile reddedilir. Düz alanları çok geniş görseller (logo, form) öz denetimden geçemezse 422 döner: "görüntü filigran taşıyamıyor".
# 1. taslak yükle (multipart) → 201 { document } curl -X POST https://jettymark.app/api/v1/media \ -H "Authorization: Bearer tm_live_…" \ -F "file=@foto.jpg" -F "title=Toplantı salonu" -F "docId=foto-2026-11-01-7" # 2. imzala → görsel: 200 MediaSignResponse · video: 202 { jobId } curl -X POST https://jettymark.app/api/v1/documents/doc_x/sign \ -H "Authorization: Bearer tm_live_…" -H "Content-Type: application/json" \ -d '{ "keyId": "key_x", "recipients": "all", "strength": 3, "maxStrength": 4 }' # → { kind: "image", version: 1, master: { markId, url, report: { strengthUsed, marginF, marginC, fLayer } }, copies: [...] } # tek istekte (CMS): yükle + imzala curl -X POST https://jettymark.app/api/v1/media/sign \ -H "Authorization: Bearer tm_live_…" \ -F "file=@klip.mp4" -F "docId=video-2026-11-01-3" -F 'recipients=["rcp_a","rcp_b"]' # → 202 { documentId, jobId } · GET /api/v1/jobs/{jobId} → { status, progress, result } # imzalı dosyayı indir (abone kopyası istek anında üretilir, önbelleklenir) curl -H "Authorization: Bearer tm_live_…" -o foto-imzali.jpg \ "https://jettymark.app/api/v1/documents/doc_x/media/1?recipient=rcp_a&download=1" # 3. herkese açık doğrulama (anonim, dosya saklanmaz) → MediaVerifyResult curl -X POST https://jettymark.app/api/v1/verify/media -F "file=@foto-imzali.jpg" # → { kind, verdict: "authentic", summary, report: { sync, frame, content: { cells } }, registry: { matched, tileDiff }, via: "server" } # video → 202 { jobId } · GET /api/v1/verify/media/jobs/{jobId}
Cihaz anahtarıyla (anahtar sunucuda değil) imzalıyorsanız: jettymark sign-media --key cihaz.json … --register https://jettymark.app --token tm_live_… dosyayı yerelde imzalar ve yalnızca 54 baytlık başlıkları POST /api/v1/marks ile kaydeder; ya da imzalı dosyayı POST /api/v1/documents/{id}/register-media ile yükleyin, sunucu imzayı yeniden doğrular.
Medya REST API
| Uç nokta | Açıklama | Kimlik |
|---|---|---|
| POST /api/v1/media | Multipart file + title?, docId?: görsel ya da video taslağı açar (küçük resim, boyut, süre, sha256) | API anahtarı · sign |
| POST /api/v1/documents/{id}/sign | Medya belgesinde { keyId, recipients, strength?, maxStrength?, allowIdOnly? }: görsel 200, video 202 + iş | API anahtarı · sign |
| POST /api/v1/media/sign | Multipart tek istek: yükle + imzala (CMS akışı) | API anahtarı · sign |
| POST /api/v1/documents/{id}/register-media | Cihaz anahtarıyla yerelde imzalanmış dosyayı kaydeder; sunucu imzayı yeniden doğrular | API anahtarı · sign |
| POST /api/v1/marks | Dosya yüklemeden işaret kaydı: { header, signature } (base64url); kid çalışma alanınıza ait olmalı | API anahtarı · sign |
| GET /api/v1/documents/{id}/media/{v} | İmzalı ana kopya ya da ?recipient= ile abone kopyası (ikili akış, x-jettymark-mark-id) | API anahtarı · documents:read |
| GET /api/v1/jobs/{id} | Video işi: queued · running · done · failed, ilerleme, sonuç | API anahtarı |
| POST /api/v1/verify/media | Multipart file ya da JSON { url }: görsel eşzamanlı, video 202 + GET /api/v1/verify/media/jobs/{id}. Dosya saklanmaz. 10 istek/dk | Anonim |
| POST /api/v1/verify/media/registry | Tarayıcıda üretilen raporu kayıt defteriyle eşler (yalnızca özet değerler; via: 'browser') | Anonim |
| POST /api/v1/trace/media | Multipart file ya da { markId }: sızan görselden abone kopyasını çözer (yalnızca kendi işaretleriniz) | API anahtarı · trace |
Yeni kapsam yok: imzalama sign, okuma documents:read, iz sürme trace. Webhook document.publish yükü kind, marks[] ve strengthUsed alanlarını da taşır. Hata sözlüğü (413 boyut, 415 tür, 422 öz denetim, 429 hız, 503 ffmpeg yok) Türkçe mesajlarla API.md'de.
Medya formatı (FORMAT-MEDIA.md)
Metin formatı gibi dondurulmuştur: bütün sabitler, fazlar ve eşikler uygunluk vektörleriyle birlikte sürüm 1'de sabitlenir; değişiklik yeni bir sürüm baytı demektir. Dayanıklılık rakamları ölçüm tamamlanana kadar tasarım hedefidir (hedef · ölçüm sürüyor).
| Bileşen | Tanım |
|---|---|
| Taşıyıcı | 128 px periyotlu, 1024 px çalışma çözünürlüğünde döşenen parlaklık deseni; frekans uzayında senkron (96 bin), kimlik katmanı C (4 ≤ r < 16) ve imza katmanı F (16 ≤ r < 36) |
| Maske ve güç | NVF tarzı doku terimi × parlaklık terimi; güç 1–5 (varsayılan 3); imzalayan JPEG 60 ve 0,5× ile öz denetim yapar, geçemezse gücü artırır ya da reddeder |
| Çerçeve (F) | sürüm(0x02/0x03) · bayraklar · kid(4) · belge(8) · zaman(4) · alıcı(4) · parça(2) · parça sayısı(2) · w8 · h8 · JMQ-25(25) · CRC-8 · imza(64) · CRC-16 = 120 bayt; K=7 hız 1/2 evrişimsel kod → 1932 kodlu bit |
| Kimlik yükü (C) | cver · cflags · markId(64) · CRC-16 = 88 bit → 188 kodlu bit; markId = SHA-256("JMM1-ID" ‖ kimlik öneki)[0..8] |
| İmzalanan mesaj | "JMM1" ‖ başlık[0..54), Ed25519; içerik özeti başlığın içinde |
| İçerik özeti | JMQ-25: 8×6 = 48 bölgenin çeyrekler arası ortalama parlaklığı, titreşimli (dither) 4 bit + 1 bayt basamak boyu; doğrulayıcı sağlam kübik ton eğrisi oturtur, eğriden 10 gri düzeyden fazla sapan bölge "uyuşmuyor"; 8'den az bölge karşılaştırılabilirse "belirsiz" |
| Doğrulama | Beyazlatma → kimlik kısa yolu → otokorelasyon kafesi → senkron kapısı (PSR ≥ 7) → afin / homografi iyileştirme → katlama → Viterbi → CRC → imza → içerik bağlaması |
| Video | 2 sn'lik parçalar; C her karede aynı, F parça başına; ≥ 4 sn'lik her kesit en az bir tam parça içerir |
| Sonuçlar | authentic · partial · modified · untrusted · damaged · unsigned + reason: cropped · uncertain · ambiguous · id_only · layer_mismatch · signature_invalid · undecodable |
Kayıt defteri ve mobil uygulama Yakında
Kamera yolu çevrimiçidir: telefon 64 bitlik işaret kimliğini okur ve kayıt defterine sorar; sonuç TANIMLANDI olarak etiketlenir, "doğrulandı" değil. Mobil uygulama planlandı; kayıt defteri API'si ve tarayıcı prototipi (/tara, deneysel) hazır. Aynı API'yi kendi uygulamanızda kullanabilirsiniz.
# anonim cihaz jetonu (isteğe bağlı; hız sınırını yükseltir) curl -X POST https://jettymark.app/api/v1/devices # → { deviceToken, expiresAt } # işaret sorgusu: yalnızca kimlikler ve ≤ 128 bit özet gider; kare, görüntü, konum gitmez curl -X POST https://jettymark.app/api/v1/marks/lookup \ -H "Content-Type: application/json" -H "X-Jettymark-Device: …" \ -d '{ "markIds": ["7c1e9a04b2d35f60"], "channel": "camera", "capture": { "regional": "a3f0…", "visibleCells": 65535 }, "confidence": { "rho": 0.41, "frames": 12, "psr": 9.8 } }' # → { marks: [{ markId, found: true, publisher: { issuer, domain, kid }, document: { kind, title?, publishedAt }, # contentMatch: "match" | "mismatch" | "unknown", verifiedOnServer: false, statement: "Bu işaret … kayıtlı; …" }] } # tek işaret, karşılaştırmasız curl https://jettymark.app/api/v1/marks/7c1e9a04b2d35f60 # CLI karşılığı jettymark lookup 7c1e9a04b2d35f60
MCP sunucusu
On bir araç: jettymark_verify, jettymark_inspect, jettymark_sign, jettymark_strip, jettymark_keygen, jettymark_trust_add, jettymark_trust_list, jettymark_sign_media, jettymark_verify_media, jettymark_inspect_media, jettymark_lookup_mark. Metin araca dosya, bağlantı ya da pano üzerinden verilir: modeller metni yeniden yazarken görünmez karakterleri düşürür, bu yüzden metin modelin elinden geçmeden araca ulaşmalıdır. Medya için aynı kural: dosya yolu ya da URL verilir; asla yeniden kodlanmış, küçültülmüş ya da ekran görüntüsü alınmış kopya değil.
Tek tık uzantı ya da yapılandırma dosyası
jettymark-<platform>.mcpb dosyasını (platforma özel paket) Ayarlar → Uzantılar'dan kurun; anahtar dosyası ve güven listesi kurulumda sorulur. Görsel araçları paketle gelir; video araçları için ffmpeg PATH'te olmalı. Ya da:
{
"mcpServers": {
"jettymark": {
"command": "node",
"args": ["/path/to/jettymark/packages/mcp/dist/stdio.js"],
"env": { "JETTYMARK_KEY": "/path/to/ege.json" }
}
}
}Plugin: araçlar + skill birlikte
Plugin, asistana ne zaman doğrulayacağını, imzalı metni nasıl taşıyacağını ve medyayı neden asla yeniden kodlamayacağını öğreten jettymark skill'ini de kurar.
# yerel geliştirme claude --plugin-dir /path/to/jettymark # pazar yerinden /plugin install jettymark --marketplace <owner>/<repo> # yalnızca MCP sunucusu claude mcp add jettymark --env JETTYMARK_KEY=/path/to/ege.json \ -- node /path/to/jettymark/packages/mcp/dist/stdio.js
config.toml
# ~/.codex/config.toml [mcp_servers.jettymark] command = "node" args = ["/path/to/jettymark/packages/mcp/dist/stdio.js"] [mcp_servers.jettymark.env] JETTYMARK_KEY = "/path/to/ege.json" # ya da tek satır codex mcp add jettymark -- node /path/to/jettymark/packages/mcp/dist/stdio.js
Streamable HTTP, durumsuz
claude.ai özel bağlayıcı, Codex --url, Cursor ve diğer istemciler için. Varsayılan olarak yalnızca doğrulama; imzalama için anahtar ve açık izin gerekir. Medya url ya da base64 ile gelir (JETTYMARK_MAX_MEDIA_BYTES, varsayılan 50 MB).
JETTYMARK_TRUST=/etc/jettymark/trusted.json \ PORT=3030 HOST=0.0.0.0 node packages/mcp/dist/http.js # https://verify.egehaber.example/mcp # /healthz → ok
Anahtar yayını
Doğrulayıcılar yayıncı anahtarını alan adınızdan alır. Panel bu dosyayı üretir; siz yalnızca barındırırsınız. Anahtar iptali de aynı dosyadan duyurulur. Aynı anahtarlar metin, görsel ve video için geçerlidir.
// https://egehaber.example/.well-known/jettymark.json { "version": 1, "issuer": "Ege Haber Ajansı", "keys": [ { "kid": "26911174", "alg": "ed25519", "publicKey": "iEcrt2Nf…bWY", "created": "2026-11-01T06:00:00Z" }, { "kid": "b02a65a8", "alg": "ed25519", "publicKey": "Qm9…x3k", "created": "2025-03-10T00:00:00Z", "revoked": "2026-09-01T00:00:00Z" } ] }
Metin formatı (FORMAT.md)
| Bileşen | Tanım |
|---|---|
| Taşıyıcı | U+2060 senkron; U+2061–U+2064 sembol (2 bit). Yalnızca kelime sonuna, boşluktan önce. |
| Kanonik metin | Görünmezler atılır, NFC, tırnak/tire/üç nokta katlanır, kelimeler tek boşlukla birleşir. |
| Çerçeve | sürüm · bayraklar · kid(4) · belge(8) · blok · sayı · zaman(4) · [alıcı(4)] · CRC-8 · imza(64) · CRC-16 = 87/91 bayt |
| İmzalanan mesaj | "TMK1" ‖ başlık ‖ SHA-256(kanonik blok), Ed25519 |
| Anahtar kimliği | SHA-256(açık anahtar)[0..4], 8 hex karakter |
| Sonuçlar | authentic · partial · modified · untrusted · damaged · unsigned |
SDK durumu
| Platform | Durum | Not |
|---|---|---|
| Node / TypeScript (metin) | Hazır | Çekirdek, CLI, MCP sunucusu |
| Görsel / video çekirdeği | Hazır | v1, deneysel eşikler: @jettymark/core/media (sharp, ffmpeg) ve /media-web; dayanıklılık ölçümü sürüyor |
| Tarayıcı (uzantı, web doğrulayıcı) | Geliştirmede | Aynı API, WebCrypto / noble ile; görsel doğrulama Web Worker'da |
| iOS / Android doğrulama uygulaması | Planlandı | Kamera ile tanımlama (yakında); kayıt defteri API'si ve tarayıcı prototipi (/tara, deneysel) hazır |
| Python | Planlandı | Doğrulama önce (metin, sonra medya), imzalama sonra |
| Go | Planlandı | Sunucu tarafı toplu imzalama |
| WordPress eklentisi | Beta | Yayın anında metin imzalama; medya ve abone dağıtımı yok |