Skip to content

Commit dc74a24

Browse files
sametbasbugclaude
andcommitted
Pano okuma, yayından kaldırma ve halka açık okuma katmanı
Selene'nin önerdiği üç işlem, biri değiştirilerek. `haber.panoOku` — `panoYaz` bir `briefId` döndürüyor ve ajan onu kaybederse (konuşma biter, oturum değişir, kalıcı hafıza yok) pano altı saat boyunca kimsenin ulaşamadığı bir yerde asılı kalıyordu. İki adımlı bir akışta ilk adımın çıktısını okuyamamak tasarım hatasıydı. `haber.yayindanKaldir` / `haber.yayinaAlGeri` — silme DEĞİL: `is_draft` ile gizleniyor, satır duruyor. Üç sınır var ve üçü de kasıtlı. Gerekçe zorunlu (gerekçesiz bir kaldırma, altı ay sonra sebebi kaybolmuş bir boşluktur), 24 saatlik pencere var, ve geri alma da ajanda — aksi halde "geri alınabilir" demek "biri veritabanına girerse geri alınabilir" demek olurdu. Pencerenin sebebi bir asimetri: yayımlamak pano, kabul sözleşmesi, tekrar kapıları ve render'dan geçiyor; kaldırmak tek çağrı. Yanlış yayını durduran kapı var, DOĞRU yayını kaldıranı yok. Kaldırılan adres 404 değil 410 dönüyor, kısa bir sayfayla. Adres bir süre yayındaydı ve paylaşımlarda karşılığı olabilir; hiç var olmamış gibi davranmak okuyucuya da arama motoruna da yanlış cevap. Gerekçe sayfada GÖSTERİLMİYOR: operatöre yazılmış bir iç not kendiliğinden yayımlanmamalı. `haber.yayinlariOku` — yeni bir yetki katmanı ve yazıldığı yer `orbit-eylem.ts`: yazma `publishers` satırı istiyor, yayımlanmış haberi okumak istemiyor. Ama açık uç değil; belge yine Orbit imzalı, yani karşıda bir Orbit kimliği ve insanın açtığı bir erişim var. `/denetim` — yayıncılara açık: son eylemler, reddedilenler, kaldırmalar. Reddedilen istek ajanda içeriksiz bir hata olarak görünüyor; sebebin okunabildiği tek yer burası. 59 vaka. Kaldırma kapılarının dördü mutasyonla sınandı; ilk turda pencere ve gerekçe kapıları HAYATTA KALDI, çünkü o yolun kendi testi yoktu. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent a8c9fc3 commit dc74a24

9 files changed

Lines changed: 934 additions & 35 deletions

File tree

‎README.md‎

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,10 +151,32 @@ dashboard: turn agent access off and the next call is refused.
151151
`publishers` row must name the agent and the human it acts for; the byline
152152
comes from that row, never from the request body.
153153

154-
Two operations exist today, and they are the two publishing endpoints:
155-
`haber.panoYaz` pins the candidate board, `haber.yayinla` publishes one story
156-
from it. The full contract lives in
157-
`orbit-project/docs/baglisite-ajan-eylemleri.md`.
154+
Six operations exist today, in two permission tiers.
155+
156+
Writing and internal state need a `publishers` row: `haber.panoYaz` pins the
157+
candidate board, `haber.panoOku` reads it back (an agent that loses the
158+
`briefId` between turns would otherwise strand a board for six hours),
159+
`haber.yayinla` publishes one story from it, and
160+
`haber.yayindanKaldir` / `haber.yayinaAlGeri` withdraw and restore one.
161+
162+
Reading published stories does not: `haber.yayinlariOku` is open to any agent
163+
whose human has connected Haber and opened agent access. Not the open web —
164+
the request still carries an Orbit-signed document — but no publisher row.
165+
166+
Withdrawal is deliberately narrower than publishing. It hides rather than
167+
deletes, requires a written reason, and only applies to stories published in
168+
the last 24 hours: the case it exists for is "we just published something
169+
wrong". Anything older is a human decision. A withdrawn address returns
170+
**410 Gone** with a short page rather than a silent 404 — it was live, it may
171+
have been shared, and pretending it never existed would be the wrong answer to
172+
both readers and crawlers.
173+
174+
Publishers can see the trail at `/denetim`: recent actions, refusals,
175+
withdrawals. Refused attempts reach the calling agent as an opaque error —
176+
Orbit does not carry a site's error body — so this page is the only place the
177+
refusal is legible.
178+
179+
The full contract lives in `orbit-project/docs/baglisite-ajan-eylemleri.md`.
158180

159181
Granting an agent is one row. `subject` is the Orbit agent id prefixed with
160182
`agent:`, `acts_for` is the human's pairwise subject as Haber knows it (the

‎public/orbit-actions.json‎

Lines changed: 230 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,65 @@
77
"idempotent": false,
88
"input": {
99
"type": "object",
10-
"required": ["board"],
10+
"required": [
11+
"board"
12+
],
1113
"additionalProperties": true,
1214
"description": "newsroom'un ürettiği pano. Alan adları Python tarafıyla aynı.",
1315
"properties": {
1416
"board": {
1517
"type": "array",
1618
"description": "Aday haberler. Her adayın en az id, title, url, source alanları olmalı.",
17-
"items": { "type": "object", "additionalProperties": true }
19+
"items": {
20+
"type": "object",
21+
"additionalProperties": true
22+
}
1823
},
19-
"task": { "type": "object", "additionalProperties": true },
20-
"policy": { "type": "object", "additionalProperties": true }
24+
"task": {
25+
"type": "object",
26+
"additionalProperties": true
27+
},
28+
"policy": {
29+
"type": "object",
30+
"additionalProperties": true
31+
}
2132
}
2233
},
2334
"output": {
2435
"type": "object",
2536
"properties": {
26-
"uygulandi": { "type": "boolean" },
27-
"briefId": { "type": "string" },
28-
"boardSize": { "type": "integer" },
29-
"expiresAt": { "type": "string" }
37+
"uygulandi": {
38+
"type": "boolean"
39+
},
40+
"briefId": {
41+
"type": "string"
42+
},
43+
"boardSize": {
44+
"type": "integer"
45+
},
46+
"expiresAt": {
47+
"type": "string"
48+
}
49+
}
50+
}
51+
},
52+
{
53+
"operationId": "haber.panoOku",
54+
"summary": "Süresi dolmamış ve kullanılmamış aktif panoyu döndürür: briefId, adaylar, görev ve geçerlilik sonu. Yayın sürecinin iç durumu.",
55+
"idempotent": true,
56+
"input": {
57+
"type": "object",
58+
"additionalProperties": false,
59+
"properties": {}
60+
},
61+
"output": {
62+
"type": "object",
63+
"description": "aktifPano null ise ortada bekleyen pano yok.",
64+
"properties": {
65+
"aktifPano": {
66+
"type": "object",
67+
"additionalProperties": true
68+
}
3069
}
3170
}
3271
},
@@ -36,34 +75,206 @@
3675
"idempotent": true,
3776
"input": {
3877
"type": "object",
39-
"required": ["briefId", "selections"],
78+
"required": [
79+
"briefId",
80+
"selections"
81+
],
4082
"additionalProperties": false,
4183
"properties": {
42-
"briefId": { "type": "string", "maxLength": 64 },
84+
"briefId": {
85+
"type": "string",
86+
"maxLength": 64
87+
},
4388
"selections": {
4489
"type": "array",
4590
"description": "Kabul sözleşmesine uyan seçim. Bugün en fazla bir haber yayımlanıyor.",
46-
"items": { "type": "object", "additionalProperties": true }
91+
"items": {
92+
"type": "object",
93+
"additionalProperties": true
94+
}
95+
},
96+
"note": {
97+
"type": "string",
98+
"maxLength": 4000
4799
},
48-
"note": { "type": "string", "maxLength": 4000 },
49100
"heroWebpBase64": {
50101
"type": "string",
51102
"description": "1200x675 WebP, base64. Zorunlu değil: görsel yoksa haber hero'suz çıkar.",
52103
"maxLength": 1400000
53104
},
54-
"heroDescribesSelection": { "type": "boolean" }
105+
"heroDescribesSelection": {
106+
"type": "boolean"
107+
}
55108
}
56109
},
57110
"output": {
58111
"type": "object",
59112
"description": "uygulandi=false ise yayın kapıları reddetti; sebep sorunlar dizisinde.",
60113
"properties": {
61-
"uygulandi": { "type": "boolean" },
62-
"durum": { "type": "integer" },
63-
"published": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
64-
"problems": { "type": "array", "items": { "type": "string" } },
65-
"contractErrors": { "type": "array", "items": { "type": "string" } },
66-
"declinedReason": { "type": "string" }
114+
"uygulandi": {
115+
"type": "boolean"
116+
},
117+
"durum": {
118+
"type": "integer"
119+
},
120+
"published": {
121+
"type": "array",
122+
"items": {
123+
"type": "object",
124+
"additionalProperties": true
125+
}
126+
},
127+
"problems": {
128+
"type": "array",
129+
"items": {
130+
"type": "string"
131+
}
132+
},
133+
"contractErrors": {
134+
"type": "array",
135+
"items": {
136+
"type": "string"
137+
}
138+
},
139+
"declinedReason": {
140+
"type": "string"
141+
}
142+
}
143+
}
144+
},
145+
{
146+
"operationId": "haber.yayindanKaldir",
147+
"summary": "Yayımlanmış bir haberi yayından kaldırır. Silmez, gizler; geri alınabilir. Yalnız son 24 saatte yayımlanmış haberler için.",
148+
"idempotent": true,
149+
"input": {
150+
"type": "object",
151+
"required": [
152+
"slug",
153+
"reason"
154+
],
155+
"additionalProperties": false,
156+
"properties": {
157+
"slug": {
158+
"type": "string",
159+
"maxLength": 200,
160+
"description": "Haberin adresindeki slug."
161+
},
162+
"reason": {
163+
"type": "string",
164+
"maxLength": 500,
165+
"description": "Gerekçe. İÇ KAYITTIR, sayfada gösterilmez. En az 10 karakter."
166+
}
167+
}
168+
},
169+
"output": {
170+
"type": "object",
171+
"properties": {
172+
"uygulandi": {
173+
"type": "boolean"
174+
},
175+
"durum": {
176+
"type": "integer"
177+
},
178+
"slug": {
179+
"type": "string"
180+
},
181+
"baslik": {
182+
"type": "string"
183+
},
184+
"kaldirildi": {
185+
"type": "boolean"
186+
},
187+
"problems": {
188+
"type": "array",
189+
"items": {
190+
"type": "string"
191+
}
192+
}
193+
}
194+
}
195+
},
196+
{
197+
"operationId": "haber.yayinaAlGeri",
198+
"summary": "Yayından kaldırılmış bir haberi geri yayına alır.",
199+
"idempotent": true,
200+
"input": {
201+
"type": "object",
202+
"required": [
203+
"slug"
204+
],
205+
"additionalProperties": false,
206+
"properties": {
207+
"slug": {
208+
"type": "string",
209+
"maxLength": 200
210+
}
211+
}
212+
},
213+
"output": {
214+
"type": "object",
215+
"properties": {
216+
"uygulandi": {
217+
"type": "boolean"
218+
},
219+
"durum": {
220+
"type": "integer"
221+
},
222+
"slug": {
223+
"type": "string"
224+
},
225+
"baslik": {
226+
"type": "string"
227+
},
228+
"yayinda": {
229+
"type": "boolean"
230+
},
231+
"problems": {
232+
"type": "array",
233+
"items": {
234+
"type": "string"
235+
}
236+
}
237+
}
238+
}
239+
},
240+
{
241+
"operationId": "haber.yayinlariOku",
242+
"summary": "Yayımlanmış haberleri en yeniden eskiye döndürür. Yayıncı yetkisi gerektirmez; Orbit'e bağlı her ajan çağırabilir.",
243+
"idempotent": true,
244+
"input": {
245+
"type": "object",
246+
"additionalProperties": false,
247+
"properties": {
248+
"limit": {
249+
"type": "integer",
250+
"minimum": 1,
251+
"maximum": 100,
252+
"description": "Kaç haber. Varsayılan 20."
253+
},
254+
"kategori": {
255+
"enum": [
256+
"Siyaset",
257+
"Ekonomi",
258+
"Teknoloji",
259+
"Bilim"
260+
],
261+
"description": "Tek kategoriye daraltır."
262+
}
263+
}
264+
},
265+
"output": {
266+
"type": "object",
267+
"properties": {
268+
"haberler": {
269+
"type": "array",
270+
"items": {
271+
"type": "object",
272+
"additionalProperties": true
273+
}
274+
},
275+
"toplam": {
276+
"type": "integer"
277+
}
67278
}
68279
}
69280
}

0 commit comments

Comments
 (0)