@wevion/cli 1.0.3881 → 1.0.3892

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.
Files changed (2) hide show
  1. package/openapi.json +982 -8
  2. package/package.json +1 -1
package/openapi.json CHANGED
@@ -31005,6 +31005,9 @@
31005
31005
  "is_internal": {
31006
31006
  "type": "boolean"
31007
31007
  },
31008
+ "marketing_excluded": {
31009
+ "type": "boolean"
31010
+ },
31008
31011
  "cohort_exclusion_reasons": {
31009
31012
  "type": "array",
31010
31013
  "items": {
@@ -32081,6 +32084,9 @@
32081
32084
  "is_internal": {
32082
32085
  "type": "boolean"
32083
32086
  },
32087
+ "marketing_excluded": {
32088
+ "type": "boolean"
32089
+ },
32084
32090
  "cohort_exclusion_reasons": {
32085
32091
  "type": "array",
32086
32092
  "items": {
@@ -33000,6 +33006,9 @@
33000
33006
  "is_internal": {
33001
33007
  "type": "boolean"
33002
33008
  },
33009
+ "marketing_excluded": {
33010
+ "type": "boolean"
33011
+ },
33003
33012
  "cohort_exclusion_reasons": {
33004
33013
  "type": "array",
33005
33014
  "items": {
@@ -252029,12 +252038,34 @@
252029
252038
  "click_query": {
252030
252039
  "type": "integer"
252031
252040
  },
252041
+ "ctr_sito_bp": {
252042
+ "description": "Site CTR of the latest day Google measured, in basis points. Null = not measured; absent in v1.",
252043
+ "anyOf": [
252044
+ {
252045
+ "type": "integer"
252046
+ },
252047
+ {
252048
+ "type": "null"
252049
+ }
252050
+ ]
252051
+ },
252032
252052
  "impression_query": {
252033
252053
  "type": "integer"
252034
252054
  },
252035
252055
  "pagine_nominate": {
252036
252056
  "type": "integer"
252037
252057
  },
252058
+ "posizione_sito_centesimi": {
252059
+ "description": "Site average position of the latest day Google measured, in hundredths. Null = not measured; absent in v1.",
252060
+ "anyOf": [
252061
+ {
252062
+ "type": "integer"
252063
+ },
252064
+ {
252065
+ "type": "null"
252066
+ }
252067
+ ]
252068
+ },
252038
252069
  "query_nominate": {
252039
252070
  "type": "integer"
252040
252071
  },
@@ -252438,12 +252469,34 @@
252438
252469
  "click_query": {
252439
252470
  "type": "integer"
252440
252471
  },
252472
+ "ctr_sito_bp": {
252473
+ "description": "Site CTR of the latest day Google measured, in basis points. Null = not measured; absent in v1.",
252474
+ "anyOf": [
252475
+ {
252476
+ "type": "integer"
252477
+ },
252478
+ {
252479
+ "type": "null"
252480
+ }
252481
+ ]
252482
+ },
252441
252483
  "impression_query": {
252442
252484
  "type": "integer"
252443
252485
  },
252444
252486
  "pagine_nominate": {
252445
252487
  "type": "integer"
252446
252488
  },
252489
+ "posizione_sito_centesimi": {
252490
+ "description": "Site average position of the latest day Google measured, in hundredths. Null = not measured; absent in v1.",
252491
+ "anyOf": [
252492
+ {
252493
+ "type": "integer"
252494
+ },
252495
+ {
252496
+ "type": "null"
252497
+ }
252498
+ ]
252499
+ },
252447
252500
  "query_nominate": {
252448
252501
  "type": "integer"
252449
252502
  },
@@ -253463,7 +253516,8 @@
253463
253516
  "copertura",
253464
253517
  "finestra",
253465
253518
  "pagine_in_calo",
253466
- "query"
253519
+ "query",
253520
+ "trend"
253467
253521
  ],
253468
253522
  "properties": {
253469
253523
  "copertura": {
@@ -253638,6 +253692,7 @@
253638
253692
  "type": "object",
253639
253693
  "required": [
253640
253694
  "clicks",
253695
+ "ctr_ultima",
253641
253696
  "impressions",
253642
253697
  "posizione_settimana",
253643
253698
  "posizione_ultima",
@@ -253648,11 +253703,22 @@
253648
253703
  "clicks": {
253649
253704
  "type": "integer"
253650
253705
  },
253706
+ "ctr_ultima": {
253707
+ "description": "Google's `ctr` (fraction 0-1) for the SAME week as `posizione_ultima` — NOT an average of the window and NOT derived from clicks/impressions: CTR does not average.",
253708
+ "anyOf": [
253709
+ {
253710
+ "type": "number"
253711
+ },
253712
+ {
253713
+ "type": "null"
253714
+ }
253715
+ ]
253716
+ },
253651
253717
  "impressions": {
253652
253718
  "type": "integer"
253653
253719
  },
253654
253720
  "posizione_settimana": {
253655
- "description": "The week `posizione_ultima` was measured on. A position without its period is not a datum.",
253721
+ "description": "The week `posizione_ultima` and `ctr_ultima` were measured on. A metric without its period is not a datum.",
253656
253722
  "type": "string"
253657
253723
  },
253658
253724
  "posizione_ultima": {
@@ -253681,6 +253747,62 @@
253681
253747
  "type": "boolean"
253682
253748
  }
253683
253749
  }
253750
+ },
253751
+ "trend": {
253752
+ "description": "The site weekly trend over the same window: clicks/impressions summed per week, position/CTR from the named day (never an average). One row per week, oldest first.",
253753
+ "type": "array",
253754
+ "items": {
253755
+ "additionalProperties": false,
253756
+ "type": "object",
253757
+ "required": [
253758
+ "clicks",
253759
+ "ctr",
253760
+ "giorno_nominato",
253761
+ "impressions",
253762
+ "posizione",
253763
+ "settimana"
253764
+ ],
253765
+ "properties": {
253766
+ "clicks": {
253767
+ "description": "Sum of the site daily clicks in this week.",
253768
+ "type": "integer"
253769
+ },
253770
+ "ctr": {
253771
+ "description": "Google's site `ctr` (fraction 0-1) for `giorno_nominato` — NOT an average of the week's days and NOT clicks/impressions.",
253772
+ "anyOf": [
253773
+ {
253774
+ "type": "number"
253775
+ },
253776
+ {
253777
+ "type": "null"
253778
+ }
253779
+ ]
253780
+ },
253781
+ "giorno_nominato": {
253782
+ "description": "The most recent day of the week that carries `posizione`/`ctr`. A metric without its period is not a datum.",
253783
+ "type": "string"
253784
+ },
253785
+ "impressions": {
253786
+ "description": "Sum of the site daily impressions in this week.",
253787
+ "type": "integer"
253788
+ },
253789
+ "posizione": {
253790
+ "description": "Google's site `avg_position` for `giorno_nominato` — the named day's value, never an average.",
253791
+ "anyOf": [
253792
+ {
253793
+ "type": "number"
253794
+ },
253795
+ {
253796
+ "type": "null"
253797
+ }
253798
+ ]
253799
+ },
253800
+ "settimana": {
253801
+ "description": "The Monday (ISO) of the week.",
253802
+ "type": "string"
253803
+ }
253804
+ }
253805
+ }
253684
253806
  }
253685
253807
  }
253686
253808
  }
@@ -270310,6 +270432,289 @@
270310
270432
  }
270311
270433
  }
270312
270434
  },
270435
+ "/api/v1/seo/sites/{siteId}/interventions/{interventionId}/withdraw": {
270436
+ "post": {
270437
+ "operationId": "withdrawSeoIntervention",
270438
+ "summary": "Withdraw a published intervention (R-I2)",
270439
+ "tags": [
270440
+ "seo"
270441
+ ],
270442
+ "description": "R-I2 — moves a `published` intervention to the terminal state `rolled_back`, the writer that was missing while the state was read in six places and written in zero. It keeps `published_url`/`published_at` so the timeline can say «it was published there, then withdrawn». Only a `published` intervention can be withdrawn; a second call, an absent one, or another team's finds nothing (404), which is also the idempotency. ⚠️ This does NOT remove the page from the customer site: the automated CMS rollback is L7 and has no write adapter yet, and for a manually-exported page the site is the customer's — the withdrawal in our records must be paired with an instruction to take it down, a surface downstream of this writer.",
270443
+ "requestBody": {
270444
+ "required": true,
270445
+ "content": {
270446
+ "application/json": {
270447
+ "schema": {
270448
+ "additionalProperties": false,
270449
+ "type": "object",
270450
+ "properties": {
270451
+ "motivo": {
270452
+ "description": "Why the intervention is being withdrawn. Recorded in the log for the audit trail; optional.",
270453
+ "maxLength": 500,
270454
+ "type": "string"
270455
+ }
270456
+ }
270457
+ }
270458
+ }
270459
+ }
270460
+ },
270461
+ "parameters": [
270462
+ {
270463
+ "schema": {
270464
+ "format": "uuid",
270465
+ "type": "string"
270466
+ },
270467
+ "in": "path",
270468
+ "name": "interventionId",
270469
+ "required": true,
270470
+ "description": "The intervention whose history is read."
270471
+ },
270472
+ {
270473
+ "schema": {
270474
+ "format": "uuid",
270475
+ "type": "string"
270476
+ },
270477
+ "in": "path",
270478
+ "name": "siteId",
270479
+ "required": true,
270480
+ "description": "The SEO site the intervention must belong to."
270481
+ }
270482
+ ],
270483
+ "security": [
270484
+ {
270485
+ "bearerAuth": []
270486
+ }
270487
+ ],
270488
+ "responses": {
270489
+ "200": {
270490
+ "description": "Successful response",
270491
+ "content": {
270492
+ "application/json": {
270493
+ "schema": {
270494
+ "additionalProperties": false,
270495
+ "type": "object",
270496
+ "required": [
270497
+ "esito",
270498
+ "ritirato_il",
270499
+ "stato"
270500
+ ],
270501
+ "properties": {
270502
+ "esito": {
270503
+ "type": "string",
270504
+ "enum": [
270505
+ "ritirato"
270506
+ ]
270507
+ },
270508
+ "ritirato_il": {
270509
+ "format": "date-time",
270510
+ "type": "string"
270511
+ },
270512
+ "stato": {
270513
+ "description": "The intervention state after the withdrawal: terminal.",
270514
+ "type": "string",
270515
+ "enum": [
270516
+ "rolled_back"
270517
+ ]
270518
+ }
270519
+ }
270520
+ }
270521
+ }
270522
+ }
270523
+ },
270524
+ "400": {
270525
+ "description": "The request was rejected before it read anything (schema, or an unresolvable scope).",
270526
+ "content": {
270527
+ "application/json": {
270528
+ "schema": {
270529
+ "description": "The request was rejected before it read anything (schema, or an unresolvable scope).",
270530
+ "anyOf": [
270531
+ {
270532
+ "additionalProperties": false,
270533
+ "description": "The request was refused; `code` says why.",
270534
+ "type": "object",
270535
+ "required": [
270536
+ "error",
270537
+ "code"
270538
+ ],
270539
+ "properties": {
270540
+ "error": {
270541
+ "type": "string"
270542
+ },
270543
+ "code": {
270544
+ "description": "Stable machine-readable reason. `FEATURE_DISABLED` on 503.",
270545
+ "type": "string"
270546
+ }
270547
+ }
270548
+ },
270549
+ {
270550
+ "description": "The request was refused by the framework layer (schema validation or role floor).",
270551
+ "type": "object",
270552
+ "required": [
270553
+ "statusCode",
270554
+ "error",
270555
+ "message"
270556
+ ],
270557
+ "properties": {
270558
+ "statusCode": {
270559
+ "type": "number"
270560
+ },
270561
+ "error": {
270562
+ "type": "string"
270563
+ },
270564
+ "message": {
270565
+ "type": "string"
270566
+ },
270567
+ "code": {
270568
+ "type": "string"
270569
+ }
270570
+ }
270571
+ }
270572
+ ]
270573
+ }
270574
+ }
270575
+ }
270576
+ },
270577
+ "401": {
270578
+ "description": "Unauthorized - missing or invalid bearer token",
270579
+ "content": {
270580
+ "application/json": {
270581
+ "schema": {
270582
+ "$ref": "#/components/schemas/ErrorResponse"
270583
+ }
270584
+ }
270585
+ }
270586
+ },
270587
+ "403": {
270588
+ "description": "The caller may not read this intervention: the role floor, or another workspace.",
270589
+ "content": {
270590
+ "application/json": {
270591
+ "schema": {
270592
+ "description": "The caller may not read this intervention: the role floor, or another workspace.",
270593
+ "anyOf": [
270594
+ {
270595
+ "additionalProperties": false,
270596
+ "description": "The request was refused; `code` says why.",
270597
+ "type": "object",
270598
+ "required": [
270599
+ "error",
270600
+ "code"
270601
+ ],
270602
+ "properties": {
270603
+ "error": {
270604
+ "type": "string"
270605
+ },
270606
+ "code": {
270607
+ "description": "Stable machine-readable reason. `FEATURE_DISABLED` on 503.",
270608
+ "type": "string"
270609
+ }
270610
+ }
270611
+ },
270612
+ {
270613
+ "description": "The request was refused by the framework layer (schema validation or role floor).",
270614
+ "type": "object",
270615
+ "required": [
270616
+ "statusCode",
270617
+ "error",
270618
+ "message"
270619
+ ],
270620
+ "properties": {
270621
+ "statusCode": {
270622
+ "type": "number"
270623
+ },
270624
+ "error": {
270625
+ "type": "string"
270626
+ },
270627
+ "message": {
270628
+ "type": "string"
270629
+ },
270630
+ "code": {
270631
+ "type": "string"
270632
+ }
270633
+ }
270634
+ }
270635
+ ]
270636
+ }
270637
+ }
270638
+ }
270639
+ },
270640
+ "404": {
270641
+ "description": "The request was refused; `code` says why.",
270642
+ "content": {
270643
+ "application/json": {
270644
+ "schema": {
270645
+ "additionalProperties": false,
270646
+ "description": "The request was refused; `code` says why.",
270647
+ "type": "object",
270648
+ "required": [
270649
+ "error",
270650
+ "code"
270651
+ ],
270652
+ "properties": {
270653
+ "error": {
270654
+ "type": "string"
270655
+ },
270656
+ "code": {
270657
+ "description": "Stable machine-readable reason. `FEATURE_DISABLED` on 503.",
270658
+ "type": "string"
270659
+ }
270660
+ }
270661
+ }
270662
+ }
270663
+ }
270664
+ },
270665
+ "500": {
270666
+ "description": "The request was refused; `code` says why.",
270667
+ "content": {
270668
+ "application/json": {
270669
+ "schema": {
270670
+ "additionalProperties": false,
270671
+ "description": "The request was refused; `code` says why.",
270672
+ "type": "object",
270673
+ "required": [
270674
+ "error",
270675
+ "code"
270676
+ ],
270677
+ "properties": {
270678
+ "error": {
270679
+ "type": "string"
270680
+ },
270681
+ "code": {
270682
+ "description": "Stable machine-readable reason. `FEATURE_DISABLED` on 503.",
270683
+ "type": "string"
270684
+ }
270685
+ }
270686
+ }
270687
+ }
270688
+ }
270689
+ },
270690
+ "503": {
270691
+ "description": "The request was refused; `code` says why.",
270692
+ "content": {
270693
+ "application/json": {
270694
+ "schema": {
270695
+ "additionalProperties": false,
270696
+ "description": "The request was refused; `code` says why.",
270697
+ "type": "object",
270698
+ "required": [
270699
+ "error",
270700
+ "code"
270701
+ ],
270702
+ "properties": {
270703
+ "error": {
270704
+ "type": "string"
270705
+ },
270706
+ "code": {
270707
+ "description": "Stable machine-readable reason. `FEATURE_DISABLED` on 503.",
270708
+ "type": "string"
270709
+ }
270710
+ }
270711
+ }
270712
+ }
270713
+ }
270714
+ }
270715
+ }
270716
+ }
270717
+ },
270313
270718
  "/api/v1/seo/sites/{siteId}/onboarding": {
270314
270719
  "get": {
270315
270720
  "operationId": "getSeoOnboarding",
@@ -270347,6 +270752,7 @@
270347
270752
  "required": [
270348
270753
  "passi",
270349
270754
  "passo_corrente",
270755
+ "piano_bloccato_da",
270350
270756
  "piano_puo_partire",
270351
270757
  "profilo",
270352
270758
  "regime_confermato",
@@ -270513,8 +270919,28 @@
270513
270919
  }
270514
270920
  ]
270515
270921
  },
270922
+ "piano_bloccato_da": {
270923
+ "description": "Why the plan cannot start, when it cannot; null when it can. `settore_escluso` is surfaced HERE, in onboarding, not only downstream at generation (B8/R-I3): an excluded sector that completes the onboarding must not read that the plan can start. The downstream generation gates stay as defence in depth.",
270924
+ "anyOf": [
270925
+ {
270926
+ "type": "string",
270927
+ "enum": [
270928
+ "passi_incompleti"
270929
+ ]
270930
+ },
270931
+ {
270932
+ "type": "string",
270933
+ "enum": [
270934
+ "settore_escluso"
270935
+ ]
270936
+ },
270937
+ {
270938
+ "type": "null"
270939
+ }
270940
+ ]
270941
+ },
270516
270942
  "piano_puo_partire": {
270517
- "description": "F14.4 — the plan does not start until the expectations tick is there. It is a prerequisite, not one of the four confirmations.",
270943
+ "description": "F14.4 — the plan starts only when all six steps are done AND the confirmed regime admits generation. An excluded sector keeps it false; `piano_bloccato_da` says which of the two is missing.",
270518
270944
  "type": "boolean"
270519
270945
  },
270520
270946
  "profilo": {
@@ -271636,6 +272062,7 @@
271636
272062
  "required": [
271637
272063
  "passi",
271638
272064
  "passo_corrente",
272065
+ "piano_bloccato_da",
271639
272066
  "piano_puo_partire",
271640
272067
  "profilo",
271641
272068
  "regime_confermato",
@@ -271802,8 +272229,28 @@
271802
272229
  }
271803
272230
  ]
271804
272231
  },
272232
+ "piano_bloccato_da": {
272233
+ "description": "Why the plan cannot start, when it cannot; null when it can. `settore_escluso` is surfaced HERE, in onboarding, not only downstream at generation (B8/R-I3): an excluded sector that completes the onboarding must not read that the plan can start. The downstream generation gates stay as defence in depth.",
272234
+ "anyOf": [
272235
+ {
272236
+ "type": "string",
272237
+ "enum": [
272238
+ "passi_incompleti"
272239
+ ]
272240
+ },
272241
+ {
272242
+ "type": "string",
272243
+ "enum": [
272244
+ "settore_escluso"
272245
+ ]
272246
+ },
272247
+ {
272248
+ "type": "null"
272249
+ }
272250
+ ]
272251
+ },
271805
272252
  "piano_puo_partire": {
271806
- "description": "F14.4 — the plan does not start until the expectations tick is there. It is a prerequisite, not one of the four confirmations.",
272253
+ "description": "F14.4 — the plan starts only when all six steps are done AND the confirmed regime admits generation. An excluded sector keeps it false; `piano_bloccato_da` says which of the two is missing.",
271807
272254
  "type": "boolean"
271808
272255
  },
271809
272256
  "profilo": {
@@ -272792,6 +273239,7 @@
272792
273239
  "required": [
272793
273240
  "passi",
272794
273241
  "passo_corrente",
273242
+ "piano_bloccato_da",
272795
273243
  "piano_puo_partire",
272796
273244
  "profilo",
272797
273245
  "regime_confermato",
@@ -272958,8 +273406,28 @@
272958
273406
  }
272959
273407
  ]
272960
273408
  },
273409
+ "piano_bloccato_da": {
273410
+ "description": "Why the plan cannot start, when it cannot; null when it can. `settore_escluso` is surfaced HERE, in onboarding, not only downstream at generation (B8/R-I3): an excluded sector that completes the onboarding must not read that the plan can start. The downstream generation gates stay as defence in depth.",
273411
+ "anyOf": [
273412
+ {
273413
+ "type": "string",
273414
+ "enum": [
273415
+ "passi_incompleti"
273416
+ ]
273417
+ },
273418
+ {
273419
+ "type": "string",
273420
+ "enum": [
273421
+ "settore_escluso"
273422
+ ]
273423
+ },
273424
+ {
273425
+ "type": "null"
273426
+ }
273427
+ ]
273428
+ },
272961
273429
  "piano_puo_partire": {
272962
- "description": "F14.4 — the plan does not start until the expectations tick is there. It is a prerequisite, not one of the four confirmations.",
273430
+ "description": "F14.4 — the plan starts only when all six steps are done AND the confirmed regime admits generation. An excluded sector keeps it false; `piano_bloccato_da` says which of the two is missing.",
272963
273431
  "type": "boolean"
272964
273432
  },
272965
273433
  "profilo": {
@@ -276402,6 +276870,7 @@
276402
276870
  "gate",
276403
276871
  "in_coda_da",
276404
276872
  "page_type",
276873
+ "revisione",
276405
276874
  "sempre_da_guardare",
276406
276875
  "target_ref",
276407
276876
  "version_number",
@@ -276731,6 +277200,33 @@
276731
277200
  }
276732
277201
  ]
276733
277202
  },
277203
+ "revisione": {
277204
+ "description": "The human-review reason: the mechanical findings with which the quality cycle ran out of retries (C4.9) and delivered the piece anyway. `null` for a piece that passed clean. It is the WHY the approver needs before asking for a change.",
277205
+ "anyOf": [
277206
+ {
277207
+ "type": "null"
277208
+ },
277209
+ {
277210
+ "additionalProperties": false,
277211
+ "type": "object",
277212
+ "required": [
277213
+ "iterazioni",
277214
+ "rilievi"
277215
+ ],
277216
+ "properties": {
277217
+ "iterazioni": {
277218
+ "type": "integer"
277219
+ },
277220
+ "rilievi": {
277221
+ "type": "array",
277222
+ "items": {
277223
+ "type": "string"
277224
+ }
277225
+ }
277226
+ }
277227
+ }
277228
+ ]
277229
+ },
276734
277230
  "sempre_da_guardare": {
276735
277231
  "description": "This row is in the sample whatever its size: its review can never be relaxed.",
276736
277232
  "type": "boolean"
@@ -278308,6 +278804,12 @@
278308
278804
  "enum": [
278309
278805
  "query_nominate_da_google"
278310
278806
  ]
278807
+ },
278808
+ {
278809
+ "type": "string",
278810
+ "enum": [
278811
+ "giorno_nominato_da_google"
278812
+ ]
278311
278813
  }
278312
278814
  ]
278313
278815
  },
@@ -278382,6 +278884,7 @@
278382
278884
  "required": [
278383
278885
  "attesa",
278384
278886
  "confronto",
278887
+ "formato",
278385
278888
  "metrica",
278386
278889
  "natura",
278387
278890
  "numero"
@@ -278481,6 +278984,29 @@
278481
278984
  }
278482
278985
  ]
278483
278986
  },
278987
+ "formato": {
278988
+ "description": "How the number reads: plain count, CTR in basis points, or a decimal rank position.",
278989
+ "anyOf": [
278990
+ {
278991
+ "type": "string",
278992
+ "enum": [
278993
+ "numero"
278994
+ ]
278995
+ },
278996
+ {
278997
+ "type": "string",
278998
+ "enum": [
278999
+ "percentuale_bp"
279000
+ ]
279001
+ },
279002
+ {
279003
+ "type": "string",
279004
+ "enum": [
279005
+ "posizione"
279006
+ ]
279007
+ }
279008
+ ]
279009
+ },
278484
279010
  "metrica": {
278485
279011
  "description": "Closed vocabulary: every metric has a source in the module.",
278486
279012
  "anyOf": [
@@ -278549,6 +279075,18 @@
278549
279075
  "enum": [
278550
279076
  "click"
278551
279077
  ]
279078
+ },
279079
+ {
279080
+ "type": "string",
279081
+ "enum": [
279082
+ "posizione_media_sito"
279083
+ ]
279084
+ },
279085
+ {
279086
+ "type": "string",
279087
+ "enum": [
279088
+ "ctr_sito"
279089
+ ]
278552
279090
  }
278553
279091
  ]
278554
279092
  },
@@ -278607,6 +279145,12 @@
278607
279145
  "enum": [
278608
279146
  "query_nominate_da_google"
278609
279147
  ]
279148
+ },
279149
+ {
279150
+ "type": "string",
279151
+ "enum": [
279152
+ "giorno_nominato_da_google"
279153
+ ]
278610
279154
  }
278611
279155
  ]
278612
279156
  },
@@ -278722,6 +279266,7 @@
278722
279266
  "required": [
278723
279267
  "attesa",
278724
279268
  "confronto",
279269
+ "formato",
278725
279270
  "metrica",
278726
279271
  "natura",
278727
279272
  "numero"
@@ -278821,6 +279366,29 @@
278821
279366
  }
278822
279367
  ]
278823
279368
  },
279369
+ "formato": {
279370
+ "description": "How the number reads: plain count, CTR in basis points, or a decimal rank position.",
279371
+ "anyOf": [
279372
+ {
279373
+ "type": "string",
279374
+ "enum": [
279375
+ "numero"
279376
+ ]
279377
+ },
279378
+ {
279379
+ "type": "string",
279380
+ "enum": [
279381
+ "percentuale_bp"
279382
+ ]
279383
+ },
279384
+ {
279385
+ "type": "string",
279386
+ "enum": [
279387
+ "posizione"
279388
+ ]
279389
+ }
279390
+ ]
279391
+ },
278824
279392
  "metrica": {
278825
279393
  "description": "Closed vocabulary: every metric has a source in the module.",
278826
279394
  "anyOf": [
@@ -278889,6 +279457,18 @@
278889
279457
  "enum": [
278890
279458
  "click"
278891
279459
  ]
279460
+ },
279461
+ {
279462
+ "type": "string",
279463
+ "enum": [
279464
+ "posizione_media_sito"
279465
+ ]
279466
+ },
279467
+ {
279468
+ "type": "string",
279469
+ "enum": [
279470
+ "ctr_sito"
279471
+ ]
278892
279472
  }
278893
279473
  ]
278894
279474
  },
@@ -278947,6 +279527,12 @@
278947
279527
  "enum": [
278948
279528
  "query_nominate_da_google"
278949
279529
  ]
279530
+ },
279531
+ {
279532
+ "type": "string",
279533
+ "enum": [
279534
+ "giorno_nominato_da_google"
279535
+ ]
278950
279536
  }
278951
279537
  ]
278952
279538
  },
@@ -285110,12 +285696,30 @@
285110
285696
  "additionalProperties": false,
285111
285697
  "type": "object",
285112
285698
  "required": [
285699
+ "fila_ordinamento",
285113
285700
  "righe",
285114
285701
  "troncato"
285115
285702
  ],
285116
285703
  "properties": {
285704
+ "fila_ordinamento": {
285705
+ "description": "How the queue is ordered: `qualita_first` (default) puts the arbiter-estimated impact (`priorita`) first, then market volume, then age — the best data-driven proposals lead the queue; `brief_first` is the historical order, market volume then age, which brings the brief keywords back to the front.",
285706
+ "anyOf": [
285707
+ {
285708
+ "type": "string",
285709
+ "enum": [
285710
+ "qualita_first"
285711
+ ]
285712
+ },
285713
+ {
285714
+ "type": "string",
285715
+ "enum": [
285716
+ "brief_first"
285717
+ ]
285718
+ }
285719
+ ]
285720
+ },
285117
285721
  "righe": {
285118
- "description": "The queue in the REAL picking order: most searched first, oldest first among equals. The same order the dispatcher uses, so what the client reads as \"next\" is what the engine will take next.",
285722
+ "description": "The queue in the REAL picking order the option above selects. The same order the dispatcher uses, so what the client reads as \"next\" is what the engine will take next.",
285119
285723
  "type": "array",
285120
285724
  "items": {
285121
285725
  "additionalProperties": false,
@@ -285124,9 +285728,14 @@
285124
285728
  "created_at",
285125
285729
  "fonte",
285126
285730
  "id",
285731
+ "intento",
285732
+ "keyword_primaria",
285733
+ "keyword_secondarie",
285127
285734
  "stato",
285735
+ "priorita",
285128
285736
  "tema",
285129
- "volume_ricerca"
285737
+ "volume_ricerca",
285738
+ "competizione_indice"
285130
285739
  ],
285131
285740
  "properties": {
285132
285741
  "created_at": {
@@ -285160,6 +285769,61 @@
285160
285769
  "format": "uuid",
285161
285770
  "type": "string"
285162
285771
  },
285772
+ "intento": {
285773
+ "description": "The search intent, or `null` when the topic has not been classified yet.",
285774
+ "anyOf": [
285775
+ {
285776
+ "description": "The search intent behind the topic, one of the four the industry labels: `commerciale`, `informativo`, `navigazionale`, `transazionale`. The same four the portfolio mix uses. `null` until it is classified.",
285777
+ "anyOf": [
285778
+ {
285779
+ "type": "string",
285780
+ "enum": [
285781
+ "commerciale"
285782
+ ]
285783
+ },
285784
+ {
285785
+ "type": "string",
285786
+ "enum": [
285787
+ "informativo"
285788
+ ]
285789
+ },
285790
+ {
285791
+ "type": "string",
285792
+ "enum": [
285793
+ "navigazionale"
285794
+ ]
285795
+ },
285796
+ {
285797
+ "type": "string",
285798
+ "enum": [
285799
+ "transazionale"
285800
+ ]
285801
+ }
285802
+ ]
285803
+ },
285804
+ {
285805
+ "type": "null"
285806
+ }
285807
+ ]
285808
+ },
285809
+ "keyword_primaria": {
285810
+ "description": "The query the article targets. `null` only on old rows; for topics seeded today it equals `tema`, because a topic that declares no keyword targets its own theme.",
285811
+ "anyOf": [
285812
+ {
285813
+ "type": "string"
285814
+ },
285815
+ {
285816
+ "type": "null"
285817
+ }
285818
+ ]
285819
+ },
285820
+ "keyword_secondarie": {
285821
+ "description": "The secondary/related keywords to cover in the body. An empty array when there are none, never null.",
285822
+ "type": "array",
285823
+ "items": {
285824
+ "type": "string"
285825
+ }
285826
+ },
285163
285827
  "stato": {
285164
285828
  "description": "DERIVED, never stored: `in_fila` waits to be picked, `in_lavoro` is bound to a production slot, `coperto` has been written, `scartato` was dropped by the client. There is no `stato` column — the database refused one, and the reason is in the migration.",
285165
285829
  "anyOf": [
@@ -285189,13 +285853,37 @@
285189
285853
  }
285190
285854
  ]
285191
285855
  },
285856
+ "priorita": {
285857
+ "description": "The impact the arbiter estimated for this topic (expected clicks/month), SEPARATE from `volume_ricerca` (market volume). `null` for brief/manual topics and for proposals whose impact is not estimable: in `qualita_first` they queue NULLS LAST, ordered among themselves by volume.",
285858
+ "anyOf": [
285859
+ {
285860
+ "type": "integer"
285861
+ },
285862
+ {
285863
+ "type": "null"
285864
+ }
285865
+ ]
285866
+ },
285192
285867
  "tema": {
285193
285868
  "type": "string"
285194
285869
  },
285195
285870
  "volume_ricerca": {
285196
- "description": "Monthly search volume when we know it. Almost always `null` today: filling it means calling the Keyword Planner, which is a later unit. A topic with no volume is still workable — it just queues by age.",
285871
+ "description": "Monthly search volume when we know it. `null` until the SEO_TOPIC_ENRICH worker writes it from the Keyword Planner, or when the GOOGLE_ADS_* env is missing. A topic with no volume is still workable — it just queues by age.",
285872
+ "anyOf": [
285873
+ {
285874
+ "type": "integer"
285875
+ },
285876
+ {
285877
+ "type": "null"
285878
+ }
285879
+ ]
285880
+ },
285881
+ "competizione_indice": {
285882
+ "description": "The Keyword Planner competition index 0-100 (0 = open field, 100 = most contested), ALONGSIDE `volume_ricerca` — a different dimension of a topic's value (difficulty, not market size). `null` until the SEO_TOPIC_ENRICH worker writes it, or when the GOOGLE_ADS_* env is missing.",
285197
285883
  "anyOf": [
285198
285884
  {
285885
+ "minimum": 0,
285886
+ "maximum": 100,
285199
285887
  "type": "integer"
285200
285888
  },
285201
285889
  {
@@ -285972,6 +286660,292 @@
285972
286660
  }
285973
286661
  }
285974
286662
  },
286663
+ "/api/v1/seo/sites/{siteId}/topics/ordinamento": {
286664
+ "patch": {
286665
+ "operationId": "setSeoTopicQueueOrder",
286666
+ "summary": "Choose how the topic queue is ordered",
286667
+ "tags": [
286668
+ "seo"
286669
+ ],
286670
+ "description": "Sets the per-site queue option: `qualita_first` (default) leads with the arbiter-estimated impact (`priorita`), then market volume, then age — the best data-driven proposals guide the queue; `brief_first` is the historical order (market volume, then age), which brings the brief keywords back to the front. The same option drives both what the client reads as \"next\" and what the dispatcher picks. Answers `SEO_SITE_NOT_FOUND` when the site is not in this workspace.",
286671
+ "requestBody": {
286672
+ "required": true,
286673
+ "content": {
286674
+ "application/json": {
286675
+ "schema": {
286676
+ "additionalProperties": false,
286677
+ "type": "object",
286678
+ "required": [
286679
+ "fila_ordinamento"
286680
+ ],
286681
+ "properties": {
286682
+ "fila_ordinamento": {
286683
+ "description": "How the queue is ordered: `qualita_first` (default) puts the arbiter-estimated impact (`priorita`) first, then market volume, then age — the best data-driven proposals lead the queue; `brief_first` is the historical order, market volume then age, which brings the brief keywords back to the front.",
286684
+ "anyOf": [
286685
+ {
286686
+ "type": "string",
286687
+ "enum": [
286688
+ "qualita_first"
286689
+ ]
286690
+ },
286691
+ {
286692
+ "type": "string",
286693
+ "enum": [
286694
+ "brief_first"
286695
+ ]
286696
+ }
286697
+ ]
286698
+ }
286699
+ }
286700
+ }
286701
+ }
286702
+ }
286703
+ },
286704
+ "parameters": [
286705
+ {
286706
+ "schema": {
286707
+ "format": "uuid",
286708
+ "type": "string"
286709
+ },
286710
+ "in": "path",
286711
+ "name": "siteId",
286712
+ "required": true,
286713
+ "description": "The SEO site whose topic queue is read or changed."
286714
+ }
286715
+ ],
286716
+ "security": [
286717
+ {
286718
+ "bearerAuth": []
286719
+ }
286720
+ ],
286721
+ "responses": {
286722
+ "200": {
286723
+ "description": "Successful response",
286724
+ "content": {
286725
+ "application/json": {
286726
+ "schema": {
286727
+ "additionalProperties": false,
286728
+ "type": "object",
286729
+ "required": [
286730
+ "fila_ordinamento"
286731
+ ],
286732
+ "properties": {
286733
+ "fila_ordinamento": {
286734
+ "description": "How the queue is ordered: `qualita_first` (default) puts the arbiter-estimated impact (`priorita`) first, then market volume, then age — the best data-driven proposals lead the queue; `brief_first` is the historical order, market volume then age, which brings the brief keywords back to the front.",
286735
+ "anyOf": [
286736
+ {
286737
+ "type": "string",
286738
+ "enum": [
286739
+ "qualita_first"
286740
+ ]
286741
+ },
286742
+ {
286743
+ "type": "string",
286744
+ "enum": [
286745
+ "brief_first"
286746
+ ]
286747
+ }
286748
+ ]
286749
+ }
286750
+ }
286751
+ }
286752
+ }
286753
+ }
286754
+ },
286755
+ "400": {
286756
+ "description": "The request was rejected before it changed anything (schema, or an unresolvable scope).",
286757
+ "content": {
286758
+ "application/json": {
286759
+ "schema": {
286760
+ "description": "The request was rejected before it changed anything (schema, or an unresolvable scope).",
286761
+ "anyOf": [
286762
+ {
286763
+ "additionalProperties": false,
286764
+ "description": "The request was refused; `code` says why.",
286765
+ "type": "object",
286766
+ "required": [
286767
+ "error",
286768
+ "code"
286769
+ ],
286770
+ "properties": {
286771
+ "error": {
286772
+ "type": "string"
286773
+ },
286774
+ "code": {
286775
+ "description": "Stable machine-readable reason. `FEATURE_DISABLED` on 503.",
286776
+ "type": "string"
286777
+ }
286778
+ }
286779
+ },
286780
+ {
286781
+ "description": "The request was refused by the framework layer (schema validation or role floor).",
286782
+ "type": "object",
286783
+ "required": [
286784
+ "statusCode",
286785
+ "error",
286786
+ "message"
286787
+ ],
286788
+ "properties": {
286789
+ "statusCode": {
286790
+ "type": "number"
286791
+ },
286792
+ "error": {
286793
+ "type": "string"
286794
+ },
286795
+ "message": {
286796
+ "type": "string"
286797
+ },
286798
+ "code": {
286799
+ "type": "string"
286800
+ }
286801
+ }
286802
+ }
286803
+ ]
286804
+ }
286805
+ }
286806
+ }
286807
+ },
286808
+ "401": {
286809
+ "description": "Unauthorized - missing or invalid bearer token",
286810
+ "content": {
286811
+ "application/json": {
286812
+ "schema": {
286813
+ "$ref": "#/components/schemas/ErrorResponse"
286814
+ }
286815
+ }
286816
+ }
286817
+ },
286818
+ "403": {
286819
+ "description": "The caller may not perform this operation: the role floor, or a site of another workspace.",
286820
+ "content": {
286821
+ "application/json": {
286822
+ "schema": {
286823
+ "description": "The caller may not perform this operation: the role floor, or a site of another workspace.",
286824
+ "anyOf": [
286825
+ {
286826
+ "additionalProperties": false,
286827
+ "description": "The request was refused; `code` says why.",
286828
+ "type": "object",
286829
+ "required": [
286830
+ "error",
286831
+ "code"
286832
+ ],
286833
+ "properties": {
286834
+ "error": {
286835
+ "type": "string"
286836
+ },
286837
+ "code": {
286838
+ "description": "Stable machine-readable reason. `FEATURE_DISABLED` on 503.",
286839
+ "type": "string"
286840
+ }
286841
+ }
286842
+ },
286843
+ {
286844
+ "description": "The request was refused by the framework layer (schema validation or role floor).",
286845
+ "type": "object",
286846
+ "required": [
286847
+ "statusCode",
286848
+ "error",
286849
+ "message"
286850
+ ],
286851
+ "properties": {
286852
+ "statusCode": {
286853
+ "type": "number"
286854
+ },
286855
+ "error": {
286856
+ "type": "string"
286857
+ },
286858
+ "message": {
286859
+ "type": "string"
286860
+ },
286861
+ "code": {
286862
+ "type": "string"
286863
+ }
286864
+ }
286865
+ }
286866
+ ]
286867
+ }
286868
+ }
286869
+ }
286870
+ },
286871
+ "404": {
286872
+ "description": "The request was refused; `code` says why.",
286873
+ "content": {
286874
+ "application/json": {
286875
+ "schema": {
286876
+ "additionalProperties": false,
286877
+ "description": "The request was refused; `code` says why.",
286878
+ "type": "object",
286879
+ "required": [
286880
+ "error",
286881
+ "code"
286882
+ ],
286883
+ "properties": {
286884
+ "error": {
286885
+ "type": "string"
286886
+ },
286887
+ "code": {
286888
+ "description": "Stable machine-readable reason. `FEATURE_DISABLED` on 503.",
286889
+ "type": "string"
286890
+ }
286891
+ }
286892
+ }
286893
+ }
286894
+ }
286895
+ },
286896
+ "500": {
286897
+ "description": "The request was refused; `code` says why.",
286898
+ "content": {
286899
+ "application/json": {
286900
+ "schema": {
286901
+ "additionalProperties": false,
286902
+ "description": "The request was refused; `code` says why.",
286903
+ "type": "object",
286904
+ "required": [
286905
+ "error",
286906
+ "code"
286907
+ ],
286908
+ "properties": {
286909
+ "error": {
286910
+ "type": "string"
286911
+ },
286912
+ "code": {
286913
+ "description": "Stable machine-readable reason. `FEATURE_DISABLED` on 503.",
286914
+ "type": "string"
286915
+ }
286916
+ }
286917
+ }
286918
+ }
286919
+ }
286920
+ },
286921
+ "503": {
286922
+ "description": "The request was refused; `code` says why.",
286923
+ "content": {
286924
+ "application/json": {
286925
+ "schema": {
286926
+ "additionalProperties": false,
286927
+ "description": "The request was refused; `code` says why.",
286928
+ "type": "object",
286929
+ "required": [
286930
+ "error",
286931
+ "code"
286932
+ ],
286933
+ "properties": {
286934
+ "error": {
286935
+ "type": "string"
286936
+ },
286937
+ "code": {
286938
+ "description": "Stable machine-readable reason. `FEATURE_DISABLED` on 503.",
286939
+ "type": "string"
286940
+ }
286941
+ }
286942
+ }
286943
+ }
286944
+ }
286945
+ }
286946
+ }
286947
+ }
286948
+ },
285975
286949
  "/api/v1/business-users": {
285976
286950
  "get": {
285977
286951
  "operationId": "getApiV1BusinessUsers",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wevion/cli",
3
- "version": "1.0.3881",
3
+ "version": "1.0.3892",
4
4
  "description": "Wevion API command-line interface — generated from the public OpenAPI spec",
5
5
  "type": "module",
6
6
  "bin": {