Geliştiriciler

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ç noktaAçıklamaKimlik
POST /api/v1/signMetni imzalar, belge kaydı açar, abone listesi verilirse kopya başına dönerAPI anahtarı
POST /api/v1/verifyMetni, 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/traceSızan metinden abone parmak izini çözerAPI anahtarı
POST /api/v1/webhooksYayın webhook'u: CMS metni gönderir, imzalı metni geri alırAPI 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ç noktaAçıklamaKimlik
POST /api/v1/mediaMultipart 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}/signMedya belgesinde { keyId, recipients, strength?, maxStrength?, allowIdOnly? }: görsel 200, video 202 + işAPI anahtarı · sign
POST /api/v1/media/signMultipart tek istek: yükle + imzala (CMS akışı)API anahtarı · sign
POST /api/v1/documents/{id}/register-mediaCihaz anahtarıyla yerelde imzalanmış dosyayı kaydeder; sunucu imzayı yeniden doğrularAPI anahtarı · sign
POST /api/v1/marksDosya 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/mediaMultipart file ya da JSON { url }: görsel eşzamanlı, video 202 + GET /api/v1/verify/media/jobs/{id}. Dosya saklanmaz. 10 istek/dkAnonim
POST /api/v1/verify/media/registryTarayıcıda üretilen raporu kayıt defteriyle eşler (yalnızca özet değerler; via: 'browser')Anonim
POST /api/v1/trace/mediaMultipart 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şenTanı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 özetiJMQ-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ğrulamaBeyazlatma → kimlik kısa yolu → otokorelasyon kafesi → senkron kapısı (PSR ≥ 7) → afin / homografi iyileştirme → katlama → Viterbi → CRC → imza → içerik bağlaması
Video2 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çlarauthentic · partial · modified · untrusted · damaged · unsigned + reason: cropped · uncertain · ambiguous · id_only · layer_mismatch · signature_invalid · undecodable
Sade anlatımTam belge: depo kökündeki FORMAT-MEDIA.md

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
statement metni spesifikasyonun Türkçe cümle setinden gelir ve asla "doğrulandı" demez. Kimlik katmanı imzasız olduğundan uyuşmazlık durumunda uygulama "işaret başka bir görsele kopyalanmış olabilir" der. Yayıncı thumbnailPublic açtıysa GET /api/v1/marks/{markId}/thumbnail kayıtlı küçük resmi döner.

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.

İmzalı metin out_file ya da to_clipboard ile, imzalı görsel ve video yalnızca out_file ile teslim edilir; sohbete yeniden yazdırılmaz. Uzak bağlayıcıda dosya yolu kapalıdır: görsel url ya da base64 data (≤ 10 MB) ile verilir, video imzalama uzak bağlayıcıda yoktur.
Claude Desktop

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" }
    }
  }
}
Claude Code

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
OpenAI Codex

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
Uzak bağlayıcı

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şenTanım
TaşıyıcıU+2060 senkron; U+2061–U+2064 sembol (2 bit). Yalnızca kelime sonuna, boşluktan önce.
Kanonik metinGörünmezler atılır, NFC, tırnak/tire/üç nokta katlanır, kelimeler tek boşlukla birleşir.
Çerçevesü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ğiSHA-256(açık anahtar)[0..4], 8 hex karakter
Sonuçlarauthentic · partial · modified · untrusted · damaged · unsigned

SDK durumu

PlatformDurumNot
Node / TypeScript (metin)HazırÇekirdek, CLI, MCP sunucusu
Görsel / video çekirdeğiHazırv1, 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ştirmedeAynı 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
PythonPlanlandıDoğrulama önce (metin, sonra medya), imzalama sonra
GoPlanlandıSunucu tarafı toplu imzalama
WordPress eklentisiBetaYayın anında metin imzalama; medya ve abone dağıtımı yok