docs: translate README into Spanish - #651
ositaemmanuel653-netizen wants to merge 910 commits into
Conversation
…onsorship feature
Extracts CLI construction into createProgram() (src/cli/program.ts) so scripts/generate-man.ts can introspect the Command tree without running the CLI, generates man/sorokeep.1, and wires build:man into npm run build. Per TegoLabs#384. Trimmed from the original PR before merging: - A full set of unrelated ".claude/agents/kfc/*", ".claude/settings/ kfc-settings.json", and ".claude/system-prompts/spec-workflow- starter.md" files - generic AI-agent workflow scaffolding with no connection to sorokeep or this issue. - getContractsByTag() and related changes to src/commands/status.ts / src/db/repositories.ts - that's issue TegoLabs#379's scope (--tag filtering), a different, unrelated feature. The PR's branch was also quite stale (predated the quiet-hours, contract_groups, rpc/client.ts any-type, and CI audit-scope fixes already on main), which produced a large raw diff and one real merge conflict in src/index.ts (this PR's createProgram() refactor vs. the already-merged --extension-jitter-ms option). Resolved by moving the jitter option registration into createProgram() so both are preserved.
…s#548) Relocates the misplaced test to tests/alerts/ (outside vitest.config.ts's include glob otherwise) and rewrites it against the current SlackChannel class / sendPagerDutyAlert function API - the old copy called a removed sendSlackAlert function.
…ted) Adds src/alerts/matrix.ts (real Matrix Client-Server API, token auth, room-scoped delivery) and its tests, per TegoLabs#310. The PR never registered the channel in builtins.ts, so `--type matrix` was unreachable from the CLI despite the sender being fully implemented and tested. Completed the registration (targetOption: "channel", since the sender's target is a Matrix room ID) plus the matching builtins.test.ts coverage, following the exact pattern used by every other lazily-imported channel (discord/telegram/opsgenie). Verified `alerts add --type matrix` end-to-end at the CLI.
… fixed + completed) Adds src/alerts/teams.ts (Adaptive Card payload, severity coloring per event type) and its tests, per TegoLabs#311. Two things fixed before merging: - CodeRabbit correctly flagged validateWebhookUrl()'s hostname check: `hostname.includes("webhook.office.com")` accepts any hostname that merely contains that substring, e.g. an attacker-controlled "x.webhook.office.com.evil.com" would pass, silently sending real alert content (contract IDs, TTL data) to an attacker-controlled server. Changed to an exact/suffix match on the real hostname, plus an explicit https-only check. Added regression tests for both. - The PR never registered the channel in builtins.ts, so `--type teams` was unreachable from the CLI. Completed the registration (targetOption: "url", matching webhook/discord's pattern) and the matching builtins.test.ts coverage.
…#585, fixed + completed) Adds src/alerts/email.ts (nodemailer SMTP transport, env/config token resolution, password redaction on error) and its tests, per TegoLabs#312. Fixed before merging: - Bumped nodemailer ^7.0.7 -> ^9.0.3 (major version, verified tsc still compiles clean and all tests pass unchanged): the pinned 7.x range had six high-severity advisories, including SMTP/CRLF command injection and an SSRF via the raw-message option. This is a production dependency, so `npm audit --omit=dev` would have failed on it. - The channel was registered in builtins.ts, but src/commands/alerts.ts still had a special-cased `--type email` branch printing "Email alerting is not yet implemented" *before* the registry was ever consulted - making the new channel completely unreachable from the CLI. Removed the special case. - Updated the one existing test that asserted the old "not implemented" behavior, and added a real success-path test (registers a config with --channel <email>). - Fixed a lint error (preserve-caught-error) the right way: the error handler already redacts the SMTP password from the thrown message, but attaching the raw caught error as `cause` would have smuggled the unredacted password back in via the cause chain. Redact the caught error's own message in place before using it as cause, so the guarantee holds through the whole chain.
…s#597, trimmed to scope) Adds src/alerts/googlechat.ts and registers it in builtins.ts, per TegoLabs#313. Registration and the sender itself were already correct. Trimmed from the original PR before merging: a bundled Grafana/Prometheus observability stack (devops/grafana/*, devops/prometheus/*, docker-compose. observability.yml, docs/observability.md) - unrelated to this issue, shared branch lineage with several other open PRs (TegoLabs#594, TegoLabs#595, TegoLabs#596) that also carry the identical bundle. Left tests/docker/docker-compose.test.ts untouched by reverting to main's version. Updated tests/alerts/builtins.test.ts for the 10th channel (the PR's branch predated matrix/teams/email, so its own copy of this file didn't know about them). Note for a follow-up: src/alerts/discord.ts has the same hostname- validation weakness fixed in TegoLabs#557 (`hostname.includes("discord")`, even looser than Teams's check) - pre-existing, not part of this PR, flagging separately.
…egoLabs#318) PR TegoLabs#568 referenced ChannelDefinition.maxRetries in dispatcher.ts but never added the field to the interface, so the branch failed to compile (TS2339). It also shipped a new dispatcher test that called registerAlertChannel("webhook", { maxRetries: 2 }) — a two-argument overload that doesn't exist on the real one-argument, throw-on-duplicate registerAlertChannel API, so the test could never have run against this codebase. - Add optional maxRetries/retryBackoffMs to ChannelDefinition (registry.ts); dispatcher.ts's lookup already existed from the merge and needed no further changes. - Give telegram a maxRetries: 3 default, matching the issue's own rationale (Telegram's Bot API rate limits are stricter than a generic webhook's) — every other channel keeps the global MAX_RETRY_COUNT default, preserving existing behavior exactly. - Rewrite the broken test to swap in a real ChannelDefinition override via the actual registry API, and restore the registry to normal built-in state afterward so it doesn't leak into other tests. Added a companion test asserting webhook has no override by default. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
# Conflicts: # package-lock.json
…nnels' into verify-555
…egoLabs#555) Issue TegoLabs#319's scope explicitly excludes the orphaned src/alerts/*.test.ts files ("reconciling those is phase-8's job, not this issue's") — they aren't in vitest.config.ts's include glob (tests/**/*.test.ts), so any tests added there never actually run. Keeping the docs update and the contract suite applied to webhook/slack, whose real test files live under tests/alerts/. Applying the contract suite to pagerduty/discord/ telegram is deferred to their dedicated orphan-reconciliation issues (TegoLabs#354-TegoLabs#356).
…to-preview-payload-without-sending-FIX' of https://github.com/veloura-dev/sorokeep into verify-582
…b/sorokeep into verify-536 # Conflicts: # src/commands/alerts.ts
…yStats (TegoLabs#536) The PR's src/db/repositories.ts shipped literal backslash-escaped backticks (\`...\`) instead of real template literals in the days-filter branch of getChannelDeliveryStats — invalid TypeScript syntax that made the entire file fail to parse (tsc reported ~30 cascading errors past this point, and CI's build-and-test check was correctly failing). Replaced with proper template literals. Also tightened the query params array from any[] to Array<number | string>. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
@ositaemmanuel653-netizen Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
📝 WalkthroughSummary by CodeRabbit
WalkthroughThe pull request adds a complete Spanish README covering Sorokeep’s usage, architecture, configuration, and contribution details. It also adds an English link to the language navigation in the main README. ChangesDocumentation translation
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related issues
Possibly related PRs
Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 6
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@README.es.md`:
- Around line 16-24: Update the navigation links in README.es.md to use the
generated Spanish fragments matching their headings: `#instalación`,
`#inicio-rápido`, `#comandos`, `#alertas`, `#contribución`, and replace the nonexistent
webhook fragment with `#firma-de-webhooks`. Preserve the existing link labels and
structure.
- Around line 598-600: Update the Core layer description in the README to
clearly state the architectural preference: it should preferably have no network
or CLI dependencies. Keep the surrounding descriptions and meaning unchanged.
- Line 1: Update the opening of README.es.md so it begins with a Markdown H1
heading, using “Sorokeep” as the heading text, before the existing centered HTML
block. Do not alter the remaining README content.
- Around line 132-144: Update the four affected fenced code blocks in
README.es.md—around the output sample, signature example, architecture diagram,
and project tree—to use text language identifiers on their opening fences. Leave
the block contents unchanged.
- Around line 371-373: Update the alert-channel references in the README
sections identified by “Alertas” and the nearby channel-support documentation so
they consistently reflect the currently supported channels, Webhook and Slack;
mark Discord, Telegram, and PagerDuty as unavailable or planned if they should
remain mentioned.
- Around line 63-82: Restore the fenced example blocks in README.es.md at the
specified sections to exactly match their corresponding blocks in README.md,
including comments, commands, and text; do not translate or otherwise modify
content inside the fences.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: d7e7dc49-c6dd-4fc6-a1dd-2f3c76797779
📒 Files selected for processing (2)
README.es.mdREADME.md
📜 Review details
🧰 Additional context used
🪛 LanguageTool
README.es.md
[style] ~204-~204: Considere alternativas para este anglicismo (recomendable sobre todo en contextos más formales).
Context: ... (requerido) | | --url <url> | URL de POST para Webhook (requerido para webhook) |...
(POST)
[style] ~393-~393: Considere alternativas para este anglicismo (recomendable sobre todo en contextos más formales).
Context: ...webhook se envían como solicitudes HTTP POST con un cuerpo JSON: ```json { "type"...
(POST)
🪛 markdownlint-cli2 (0.23.1)
README.es.md
[warning] 1-1: First line in a file should be a top-level heading
(MD041, first-line-heading, first-line-h1)
[warning] 132-132: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 209-209: Link fragments should be valid
(MD051, link-fragments)
[warning] 421-421: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 470-470: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 553-553: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🔇 Additional comments (1)
README.md (1)
4-7: LGTM!
| @@ -0,0 +1,702 @@ | |||
| <p align="center"> | |||
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Resolve the reported MD041 violation.
README.es.md starts with a centered HTML block, not a Markdown H1. Use a Markdown # Sorokeep heading, or configure the Markdown linter to allow this HTML heading pattern.
Static analysis reports MD041 at Line 1.
🧰 Tools
🪛 markdownlint-cli2 (0.23.1)
[warning] 1-1: First line in a file should be a top-level heading
(MD041, first-line-heading, first-line-h1)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@README.es.md` at line 1, Update the opening of README.es.md so it begins with
a Markdown H1 heading, using “Sorokeep” as the heading text, before the existing
centered HTML block. Do not alter the remaining README content.
Source: Linters/SAST tools
| <a href="#install">Instalación</a> | ||
| · | ||
| <a href="#quick-start">Inicio Rápido</a> | ||
| · | ||
| <a href="#commands">Comandos</a> | ||
| · | ||
| <a href="#alerting">Alertas</a> | ||
| · | ||
| <a href="#contributing">Contribución</a> |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Use fragments that exist in README.es.md.
The navigation uses English fragments such as #install and #quick-start, but the headings are Spanish. The webhook link also targets nonexistent #webhook-signing.
Use the generated Spanish fragments, for example #instalación, #inicio-rápido, #comandos, #alertas, #contribución, and #firma-de-webhooks.
Also applies to: 209-209
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@README.es.md` around lines 16 - 24, Update the navigation links in
README.es.md to use the generated Spanish fragments matching their headings:
`#instalación`, `#inicio-rápido`, `#comandos`, `#alertas`, `#contribución`, and replace
the nonexistent webhook fragment with `#firma-de-webhooks`. Preserve the existing
link labels and structure.
Source: Linters/SAST tools
| ```bash | ||
| # Desde el código fuente | ||
| git clone https://github.com/AbdulmalikAlayande/sorokeep.git | ||
| cd sorokeep | ||
| npm install | ||
| npm run build | ||
|
|
||
| # Ejecutar directamente | ||
| npx tsx src/index.ts --help | ||
|
|
||
| # O vincular globalmente después de compilar | ||
| npm link | ||
| sorokeep --help | ||
|
|
||
| # Instalar el manual local | ||
| mkdir -p ~/.local/share/man/man1 | ||
| cp man/sorokeep.1 ~/.local/share/man/man1/ | ||
| mandb 2>/dev/null || true | ||
| man sorokeep | ||
| ``` |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
python - <<'PY'
from pathlib import Path
import re
import sys
def blocks(path):
text = Path(path).read_text(encoding="utf-8")
return re.findall(r"^```([^\n]*)\n(.*?)^```\s*$", text, re.MULTILINE | re.DOTALL)
english = blocks("README.md")
spanish = blocks("README.es.md")
if len(english) != len(spanish):
print(f"Different fenced-block counts: {len(english)} vs {len(spanish)}")
sys.exit(1)
for index, (left, right) in enumerate(zip(english, spanish), 1):
if left != right:
print(f"Fenced block {index} differs")
sys.exit(1)
print("All fenced blocks match.")
PYRepository: AbdulmalikAlayande/sorokeep
Length of output: 188
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
from pathlib import Path
import re
def blocks(path):
text = Path(path).read_text(encoding="utf-8")
return re.findall(r"^```([^\n]*)\n(.*?)^```\s*$", text, re.MULTILINE | re.DOTALL)
english = blocks("README.md")
spanish = blocks("README.es.md")
print("fenced_block_count =", len(english), "vs", len(spanish))
for i, (lhs, rhs) in enumerate(zip(english, spanish), 1):
lang_lhs, lang_rhs = lhs.split(",", 1)[0].strip() if "," in lhs else "(no-lang)", rhs.split(",", 1)[0].strip().split("\n", 1)[0] if "," in rhs else ""
print(f"\n--- block {i} ---")
print("lang lhs:", lang_lhs)
print("lang rhs:", lang_rhs)
print("lhs:")
print(lhs)
print("rhs:")
print(rhs)
print("match:", lhs == rhs)
PY
sed -n '63,84p;89,110p;259,277p;318,328p' README.es.mdRepository: AbdulmalikAlayande/sorokeep
Length of output: 21012
Keep fenced example content unchanged.
Both translated shell comments and untranslated example text alter the source blocks. Restore the original fenced examples at README.es.md lines 63-82, 89-110, 261-276, 321-327, and 619-628 to match README.md.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@README.es.md` around lines 63 - 82, Restore the fenced example blocks in
README.es.md at the specified sections to exactly match their corresponding
blocks in README.md, including comments, commands, and text; do not translate or
otherwise modify content inside the fences.
| ``` | ||
| $ sorokeep watch CDLZFC3S...CYSC --network testnet --name "XLM Native Token" | ||
|
|
||
| ✔ Contract XLM Native Token registered successfully. | ||
|
|
||
| Contract: XLM Native Token (CDLZFC3S...CYSC) | ||
| Network: testnet | ||
| Entries: 1 discovered | ||
| Instance TTL: 113,918 ledgers (~7d 6h) OK | ||
|
|
||
| Run 'sorokeep status CDLZFC3S...CYSC' to check TTLs anytime. | ||
| Run 'sorokeep guard CDLZFC3S...CYSC' to enable auto-extension. | ||
| ``` |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Add language identifiers to the fenced blocks.
Markdownlint reports MD040 for the output sample, signature example, architecture diagram, and project tree. Use text for these blocks.
Static analysis reports MD040 at Lines 132, 421, 470, and 553.
Proposed change
-```
+```textAlso applies to: 421-423, 470-509, 553-594
🧰 Tools
🪛 markdownlint-cli2 (0.23.1)
[warning] 132-132: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@README.es.md` around lines 132 - 144, Update the four affected fenced code
blocks in README.es.md—around the output sample, signature example, architecture
diagram, and project tree—to use text language identifiers on their opening
fences. Leave the block contents unchanged.
Source: Linters/SAST tools
| ## Alertas | ||
|
|
||
| Sorokeep entrega alertas a través de múltiples canales: **webhooks**, **Slack**, **Discord**, **Telegram** y **PagerDuty**. Cada alerta incluye un nivel de severidad y contexto detallado sobre la entrada afectada. Sorokeep utiliza una arquitectura de despacho y detección desacoplada robusta con una cola respaldada por base de datos. |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Reconcile the supported alert-channel list.
Line 373 lists Webhook, Slack, Discord, Telegram, and PagerDuty. Lines 203 and 674 state that only Webhook and Slack are supported. Update the documentation consistently, or mark the additional channels as unavailable or planned.
Also applies to: 672-674
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@README.es.md` around lines 371 - 373, Update the alert-channel references in
the README sections identified by “Alertas” and the nearby channel-support
documentation so they consistently reflect the currently supported channels,
Webhook and Slack; mark Discord, Telegram, and PagerDuty as unavailable or
planned if they should remain mentioned.
| - **Commands** (`src/commands/`) — Capa delgada de CLI. Analiza los argumentos, llama a core y formatea la salida de la terminal. Sin lógica de negocios. | ||
| - **Core** (`src/core/`) — Lógica de negocio pura. Probable sin red o CLI. El daemon reutiliza las mismas funciones. | ||
| - **RPC** (`src/rpc/`) — Wrapper del SDK de Stellar. Todas las llamadas de red pasan por aquí. Maneja la construcción de transacciones, la simulación, la firma y el envío. |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Correct the Core-layer description.
Probable sin red o CLI is unclear Spanish and does not express the intended architecture constraint. Replace it with wording such as Preferiblemente sin dependencias de red ni de la CLI.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@README.es.md` around lines 598 - 600, Update the Core layer description in
the README to clearly state the architectural preference: it should preferably
have no network or CLI dependencies. Keep the surrounding descriptions and
meaning unchanged.
43ad363 to
8692701
Compare
What does this PR do?
Closes #475.
Adds a full Spanish translation of the project documentation by creating
README.es.md, preserving all code blocks, commands, and CLI flags in their original form. Also adds a language switcher at the top of bothREADME.mdandREADME.es.mdso readers can easily navigate between the English and Spanish versions.Why?
This expands Sorokeep's documentation accessibility for the large Spanish-speaking Stellar and Soroban developer community, making it easier for developers across Latin America and other Spanish-speaking regions to discover, install, and use the project.
Additionally, this PR acknowledges that translated documentation is a living artifact that should be kept in sync as the primary English README evolves. I am willing to help maintain the Spanish translation as future documentation changes are introduced.
Does this touch secret-key handling or transaction submission?
Additional Notes
README.es.mdincludes every section present inREADME.md, with no sections omitted or left untranslated (excluding code blocks, command names, and flags, which intentionally remain unchanged).README.mdandREADME.es.md.Checklist
npm test)npx tsc --noEmit)npm run lint)console.login core logic