Pixel

Pixel Updates & Events

Server Updates & Events

Announcements

Fix Docker Daemon Configuration Errors in CI

DEV Community

Unable to configure the Docker daemon with file daemon.json in CI

Unable to configure the Docker daemon with file daemon.json is dockerd refusing to start because it could not turn your configuration file into a usable configuration. The sentence is only a wrapper: what actually went wrong is in the clause that follows the file name, and it is either the file failing to parse or an option being set in two places at once. Flags and the file are merged before anything starts. A parse failure and a duplicate directive both stop it there. What this error means Every Docker command in the job fails to connect, and the reason is not in the job log at all, because the daemon never came up to write one. On a runner you provision yourself, this typically follows a provisioning step that wrote /etc/docker/daemon.json for a registry mirror, a log driver or a storage option, and the workflow that used to work now fails at its first container. The daemon logs the real line to the system journal, so the failure is invisible until you go and look there. ```The line docker/for-linux#327 reports from dockerd (quoted, not a recorded run) unable to configure the Docker daemon with file /etc/docker/daemon.json: the following directives are specified both as a flag and in the configuration file: insecure-registries: (from flag: [192.168.0.2:5000], from file: [192.168.0.2:5000])

Common causes

The file is not valid JSON

A trailing comma, an unquoted key, a smart quote pasted from a document, or a stray brace. The Go decoder reports the character and what it expected, which is enough to find the spot, and the daemon refuses to start rather than guessing at what you meant.

An option is set both as a flag and in the file

The daemon checks for this deliberately and aborts rather than picking a winner. The classic is a registry or host setting present in a systemd unit override and in daemon.json at the same time, usually because two different guides were followed months apart.

A key is misspelled or not supported by this version

Configuration keys change between Docker releases, and a key copied from a newer version of the documentation onto an older daemon is rejected at startup. In our experience this is the cause when the file is obviously valid JSON and the message still names the file rather than a parse position.

A provisioning step appended to the file with text tools

Shell redirection that adds a key to an existing JSON object produces a file that looks right and is not. This is the mechanism behind most of the parse failures above, and it is worth naming separately because the fix is to change how the file is written, not just to repair it once.

How to fix it

Validate the file in the step that writes it

  1. Parse the file with a real JSON parser immediately after writing it.
  2. Fail the provisioning step on a parse error, before anything restarts the daemon.
  3. Only then restart Docker, and check the unit actually came back up.

```Terminal
sudo tee /etc/docker/daemon.json >/dev/null <<'JSON'
{ "registry-mirrors": ["https://mirror.example.internal"] }
JSON
python3 -c "import json; json.load(open('/etc/docker/daemon.json'))"
sudo systemctl restart docker && sudo systemctl is-active docker
Keep every option in one place Pick either the systemd unit flags or daemon.json for each setting and remove it from the other. The daemon refuses to start when the same directive appears twice, so a duplicate is not a style problem that can wait; it is the whole failure. systemctl cat docker | grep -n ExecStart
sudo cat /etc/docker/daemon.json
Edit JSON with a JSON tool Use a parser to add or change keys, so the file is re-emitted as valid JSON every time instead of being patched as text. This removes the trailing comma class of failure permanently rather than fixing one instance of it. tmp=$(mktemp)
jq '."log-driver" = "json-file"' /etc/docker/daemon.json > "$tmp" \
&& sudo mv "$tmp" /etc/docker/daemon.json
Surface the daemon journal in the failing job Add a failure-only ste...

Powered by Readybot.io

Fix Docker Daemon Configuration Errors in CI

Building Safer Health Apps for Teenagers

DEV Community

What People Assume About Building a Health App for Teenagers

Ask someone outside the industry what a cycle tracking app does and you will usually get a short answer: it logs dates and predicts the next one. That answer is not wrong, but it is roughly the equivalent of saying a banking app stores your balance. The feature list is real. It just is not where the product succeeds or fails. The gap between that expectation and the reality of building for young users is where most of the expensive mistakes live. These are the assumptions worth challenging before anyone opens a design tool. Myth: The hard part is the prediction logic Cycle prediction is maths, and the maths is well understood. What is genuinely hard is what happens around it. A young user opens the app on a day when she feels awful, and the screen either explains something or it does not. Raw data with no interpretation leaves her more anxious than before she opened it. Personalised insight is the product. The calendar is the interface. Teams that budget their effort the other way round end up with a technically accurate app that nobody opens twice. Myth: A chatbot is a feature you bolt on An AI companion inside a health app is not a support widget. Tone, boundaries and the handling of sensitive disclosures all become product decisions, not support decisions. A response that would be fine in a shopping app can be actively harmful when someone describes a symptom or a bad week. This is why the chatbot work has to be shaped by health expertise and tested with real users from the target age group, not written by whoever happens to be free. The question is never "can it answer" but "should it answer this, and in what register". Myth: Privacy is a compliance checkbox For an app aimed at under-18s, data handling is a design constraint that shapes architecture, not a document you attach at the end. Consent, retention, encryption and what the AI is allowed to see all interact with each other. Retrofitting them after the build is where timelines die. Users feel this even when they cannot name it. A teenager who senses an app is careless with her information will not tell you she noticed. She will simply stop logging honestly, and the personalisation quietly degrades into guesswork. Myth: Premium features are just gated screens There is a real tension in health apps between monetisation and trust, and it is sharper when the audience is young. Paywalling the emotional support or the clearer explanations reads as holding reassurance hostage, and users respond to that. A good result looks like a free experience that still feels complete, with paid tiers offering depth rather than relief. That is a positioning decision made early, not a paywall toggled late. What good actually looks like The apps that earn long-term trust tend to share a shape: clear explanations instead of raw numbers, emotional support that stays within safe bounds, privacy built into the architecture, and a premium model that does not punish the anxious user. None of that is exotic. It is just rarely the thing teams plan for first. The full breakdown of how those decisions were made on a live AI health app, including the research, safety and subscription choices, is in the Ove Care case study.

Powered by Readybot.io

Building Safer Health Apps for Teenagers

Polite Payment Reminder SMS: Samples and Rules

DEV Community

Polite Payment Reminder SMS: Samples and How to Send

A polite payment reminder SMS names your business, states the amount and due date, and gives one easy way to pay, all within 160 characters and with no pressure words. Send the first one before the due date and firm up slowly. Where your country requires it, register the sender and wording first, as India's DLT system does. This guide gives you samples you can adapt, a schedule, and the sender rules that decide whether your message arrives at all. Note: Key takeaways Politeness is mostly facts. A clear amount, reference, and date let you stay kind without sounding vague. Keep offers out. In most regimes, one discount line can turn a reminder into a marketing message, with stricter rules. Small characters change the bill. An accented letter, a curly apostrophe, or a word in a non-Latin script moves a message to a smaller segment size, so check length when it matters. Send between 10:00 and 19:00 local time. That range sits inside every window we could find, including US TCPA hours and the lender contact windows we checked. Register what your regime asks for. Some registries check the links and callback numbers in a template as well as the wording. What makes a payment reminder SMS polite? A polite reminder assumes the best while still being exact. Most people who get one haven't refused to pay. They may have missed the date, be waiting for a salary, or have paid an hour ago. Being polite doesn't mean being unclear. Avoid both extremes, the message too soft to act on and the one that picks a fight. These swaps keep you in the middle: Instead of Write Why it works You failed to pay We have not seen your payment yet It states what you know, not what they did URGENT!!! Please pay by 20 Nov A date creates urgency without shouting Final warning This is our last reminder before [next step] It explains what happens next Legal action will follow Name a step only if your contract allows it and you will take it Empty threats damage trust Why haven't you paid? Something wrong? Call us on [helpline] It invites a conversation Please do the needful Please pay $450 using this link It says exactly what you want Also leave out anything private. A text can appear on a locked screen or on a shared family phone, so skip words such as defaulter, and don't mention other people. Polite payment reminder SMS samples by stage Replace the words in brackets with your own details. Character counts use short example values: a five-letter name, a four-letter business, $450, invoice INV2291, a date like 20 Nov, a 10-digit helpline, a 24-character link, and five characters for any other bracket. Count again with your longest real values. Every sample stays inside one GSM-7 segment at those lengths. Stage Sample Characters 3 days before Hi [name], a note from [business]: $[amount] for invoice [invoice] falls due on [date]. You can pay at [link]. Already paid? Thank you. 139 Due day Hi [name], your [business] payment of $[amount] is due today. It takes a minute to pay here: [link]. Thank you. 117 3 days late Hi [name], we have not seen $[amount] for invoice [invoice] yet. It may have slipped by, so here is the link again: [link]. Thanks, [business] 146 7 days late Hi [name], $[amount] on invoice [invoice] is 7 days past due. Please pay by [new date]: [link]. Something wrong? Call [helpline]. [business] 140 14 days late Hi [name], if paying $[amount] in full is hard right now, we would like to help. Call [helpline] to discuss part payment or a new date. [business] 134 30 days late Hi [name], $[amount] on invoice [invoice] is unpaid. Please pay by [new date] to keep your service active: [link]. To talk, call [helpline]. [business] 151 After payment Thank you, [name]. We received $[amount] for invoice [invoice] on [date]. Your receipt: [link]. [business] 110 The 14-day message adds help instead of pressure. Only send the 30-day wording if service really will stop on that date. If your messages go out from a sender header rather than a phone number, as business S...

Powered by Readybot.io

Polite Payment Reminder SMS: Samples and Rules

The IDOR Iceberg: 4 Flaws Scanners Often Miss

DEV Community

The IDOR Iceberg: Why Scanners Miss 95% of Object-Reference Flaws

If your IDOR knowledge stops at changing id=101 to id=102, you're missing 95% of real business-logic bugs. Here's the iceberg below the waterline. Modern APIs mostly dropped sequential integer IDs in favour of UUIDv4, opaque tokens and nested GraphQL. Automated scanners only know how to tamper with trivial integers, so they are blind to modern IDOR topologies. Here's the IDOR iceberg — the patterns worth hunting on enterprise APIs. 1. GraphQL alias field projections A single GraphQL request can ask for the same type under multiple scopes via aliases: query {
mine: user(id: "uuid-my-account") { email role }
target: user(id: "uuid-victim-account") { email role }
}
Authorization middleware often evaluates permission on the first resolved field and never iterates the alias tree. 2. UUID-to-integer cast boundaries Many services expose UUIDs at the gateway but keep integer primary keys internally: GET /api/documents/00000000-0000-0000-0000-000000001337
GET /api/documents/1337
If the backend strips hyphens or silently casts a failed UUID parse to an integer, the auth check breaks while the DB query still succeeds. 3. Pre-signed cloud storage URLs File flows generate pre-signed URLs (S3, GCS, Azure Blob): POST /api/export/generate
{ "export_type": "pdf", "storage_reference_id": "org_victim_financials" }
If the client controls storage_reference_id or bucket_key, the backend may sign a grant to another tenant's bucket. 4. Batch operations and array injection POST /api/v2/contacts/batch-delete
{ "account_id": "org_my_company",
"contact_ids": ["contact_mine_1", "contact_victim_99"] }
The auth layer checks that you own account_id — but never that every ID in the array does, before running the batch transaction. The takeaway IDOR is not a parameter flaw. It's an architectural access-control failure. Don't trust scanners to find logic bugs. Map how objects move across services, watch where type conversions happen, and scrutinize every batch endpoint. Which IDOR variant gave you your highest-impact report? Share it below.

Powered by Readybot.io

The IDOR Iceberg: 4 Flaws Scanners Often Miss

Vibe Coding Observability Before Production

DEV Community

Vibe coding observability: what to check before production

On a Monday morning a team merges an order export written almost entirely by a coding assistant. Tests are green, the review finds nothing odd, the endpoint returns 200. Three weeks later a customer reports missing rows in their file. That is the real question behind vibe coding observability: not « is the AI any good at coding? » but « what proves, in production, that this code does what I think it does? » I start from that operating problem rather than from a feature list. There are three decisions to make: where to put spans, what to look at in Dynatrace SaaS, and what to demand before a merge. For the vendor’s own take, read its post on runtime; the structure and examples below are mine. Method: I ran the Python code in the screenshots with opentelemetry-sdk 1.45.2 and show the real output. I did not run the DQL queries or send any data to a Dynatrace environment, so they are marked « not verified ». Everything applies to Dynatrace SaaS; Managed is not covered. Why vibe coding observability is not a separate discipline An assistant writes plausible code. It compiles, it passes the tests it wrote itself, it handles the happy path. What it lacks is knowledge of your production: real volumes, dirty data, slow dependencies. That is no moral failing, just a blind spot: nobody gave it that context. I quote no figure on the quality of generated code, because I have not read a study I could check. The argument holds without one. The more code you accept without writing it line by line, the more the proof must come from execution rather than reading. It is plain SRE hygiene: a measured SLI beats declared confidence. Do not mix up two jobs. Monitoring the assistant itself (cost, usage, sessions) is covered in monitoring a coding agent. This article is about the code the assistant delivers once it runs in production. For getting started with an AI-assisted IDE, the ThinkRail piece is a different subject. A textbook case: 200 OK and a quarter of the rows gone I rebuilt the scenario in twenty lines. The function does what assistants often do: loop over orders, run one query per order to find the customer, and wrap everything in a try/except that swallows any error so the export « never crashes ». Two classic flaws hide in there. First, one query per order: 1 + 40 queries for 40 rows. Second, the exception is ignored, so the response stays green. Here is the actual run. The response claims success, yet 10 orders out of 40 are missing: one customer is absent from the table. One HTTP request produced 41 spans: the signature of an N+1. The root span stays UNSET, so an SLI computed on it alone would see nothing. The 10 child spans carry ERROR and the message: that is where the truth settled. First decision: instrument the low layer, not the handler The lesson is architectural. The span recorded the error because the exception crossed the with block in query_one before the calling code silenced it. Had I wrapped only the handler, I would have got a green span. A practical rule: put spans as close as possible to outgoing calls (database, HTTP, message queue), where generated code cannot hide them by catching everything. OpenTelemetry instrumentation libraries often do this for you; I did not check which ones cover your driver. To know what a span holds, read the anatomy of an OpenTelemetry span. Second rule: ban except Exception: pass in review unless it logs or counts. That is not purism. It is the line that manufactures invisible incidents. Sending the telemetry to Dynatrace SaaS According to the OTLP page of the documentation, the SaaS endpoint is https://{environment-id}.live.dynatrace.com/api/v2/otlp, with /v1/traces for traces. Authentication uses an Authorization: Bearer header and a token with the openpipeline:traces:ingest scope. Transport is HTTP with binary Protobuf: neither gRPC nor JSON. So set OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf, or go through a Collector that converts. If you copy the ID from the browser address bar, ...

Powered by Readybot.io

Vibe Coding Observability Before Production

EU Law Search Benchmark: 102 Questions Tested

DEV Community

102 EU compliance questions we had never seen: our law index found the article first 76 times, a web search API 34

Yesterday we published a small test: 20 EU compliance questions, our EU law search against Exa's web search. Fair criticism of a 20-question test is that we might have tuned our ranking on exactly those 20. We did. So today we wrote 102 new questions and ran them before touching the ranking. The test 102 questions across 41 EU acts: GDPR, the AI Act, DSA, DMA, NIS2, DORA, MiCA, the VAT Directive, PSD2, the anti-money-laundering rules, consumer, product-safety and sustainability law. Each question names the article a correct answer must cite ("when must a company appoint a data protection officer" → GDPR Article 37). Every expected article was checked against the law's own text before either search ran. Ours counts only when the result is that article. Exa (search type auto, 5 results) counts when the title, URL or first 1,500 characters name the article number and the act, a deliberately lenient rule. Results Right article first Right article in top 5 Our EU law index 76 / 102 96 / 102 Exa search (auto) 34 / 102 75 / 102 On the 20 questions we did tune on, the picture is the same: ours 10 and 19, Exa 4 and 13. Why the gap A web search returns pages about the law: regulators' guidance, law-firm explainers, glossaries. Those are useful, but an agent that has to cite a provision needs the provision. Our index holds 47 EU acts article by article, in their latest consolidated text from the EU's own publications office, hosted in the EU. Where we lost Six questions had no right article in our top 5. Three were VAT questions: the VAT Directive's articles carry no headings in the official text, which our ranking leans on. "Health data" pulled up the European Health Data Space instead of GDPR Article 9. We will fix these against a fresh set of questions, not these 102. Limits, plainly We wrote the questions. They are checked against the law, not against either search, and they are public. The questions do not say "EU"; some of Exa's answers were UK or US pages, which a question naming the EU might avoid. English only so far. Try it The 122 questions with their expected articles and both scoring scripts (ours, Exa's) are in our public repository, so anyone can re-run them. If you already use Exa's SDK, point it at our base URL: the same search, contents and answer calls work, including structured answers, and EU-law questions are answered from the index. from exa_py import Exa
exa = Exa(api_key="YOUR_KEY", base_url="https://tools.funwords.eu/v1")
exa.search("when must a company appoint a data protection officer", category="law", num_results=5)
Every result carries the act, the article, its text and the EUR-Lex link. Send us your hardest compliance questions and we will add them to the next run.

Powered by Readybot.io

EU Law Search Benchmark: 102 Questions Tested

GitHub Actions Reusable Workflow Environment Variables

DEV Community

GitHub Actions reusable workflow env not inherited by the called file

GitHub Actions reusable workflow env not inherited is documented behavior rather than a bug, and the restriction is stricter than most people expect: the calling job cannot even declare an env block, because the schema shape for a job with uses has no such key. Values cross that boundary as inputs, as secrets or as organization variables, and as nothing else. Three things cross the call and two do not. The two that do not are the two people reach for first. What this error means The called workflow reads a variable the caller set and gets an empty string. The same env block works perfectly for the caller's own jobs, which is what makes this read as a scoping subtlety rather than a hard boundary. If you then try the obvious repairs, they fail in two different ways: adding env to the calling job is rejected when the file is parsed, and passing the value through with using an env expression is rejected as an unrecognized named-value. Neither message mentions reusable workflows. ```Quoted from the title of actions/runner#2372 Unrecognized named-value: 'env'. Located at position 1 within expression

Common causes

Expecting workflow-level env to propagate

The commonest cause and the most reasonable expectation, because env does reach every job and every step inside the file that declares it. The boundary is the call, not the file, and the documentation lists the behavior among the limitations of reusable workflows rather than among the rules for env, which is why it is easy to miss.

Treating a called workflow like a composite action

A composite action runs inside the calling job and shares its environment, so habits formed there transfer badly. A called workflow runs as its own jobs, on its own runners, with a fresh environment, so there is no shared process for a variable to survive in.

Passing the value with an env expression

Reaching for with: key: ${{ env.VALUE }} on the calling job. The context list for that key does not include env, so this fails as an unrecognized named-value rather than as an empty string, and the message names the context instead of the boundary.

Computing the value in a step of the caller

Writing to $GITHUB_ENV in one job and expecting a later calling job to see it. Environment changes do not cross jobs at all, reusable workflow or not, and the call is a job rather than a step, so there is nowhere for a step-scoped value to be read from.

How to fix it

Declare an input and pass the value explicitly

Give the reusable workflow a typed input and pass it from the caller. This is the documented mechanism, it is readable at the call site, and it makes the contract between the two files visible to anyone editing either one.

```.github/workflows/build.yml and ci.yml (illustrative)

build.yml

on:
workflow_call:
inputs:
app_env:
type: string
required: true

ci.yml

jobs:
call:
uses: ./.github/workflows/build.yml
with:
app_env: staging
Use a variable for anything shared across workflows Repository and organization variables are readable in both files without being passed, which removes the plumbing entirely. The documentation makes the same recommendation for reusing values across workflows, and it is the right answer for things like an environment name, a region or a registry host. ```.github/workflows/build.yml (illustrative) steps: - run: ./deploy.sh --env "${{ vars.APP_ENV }}"

Publish a computed value as a job output first

  1. Compute the value in an ordinary job in the caller and write it to $GITHUB_OUTPUT.
  2. Map it to a job output with an outputs block on that job.
  3. Add needs on the calling job so the needs context resolves.
  4. Pass it through with, reading needs.<job>.outputs.<name>, which is a context that key accepts.

```.github/workflows/ci.yml (illustrative)
call:
needs: prepare
uses: ./.github/workflows/build.yml
with:
app_env: ${{ needs.prepare.outputs.app_env }...

Powered by Readybot.io

GitHub Actions Reusable Workflow Environment Variables

Calculate Wallpaper Rolls with JavaScript

DEV Community

How to Calculate How Much Wallpaper You Need (Without Running Short)

Hanging wallpaper is expensive. If you don't account for the pattern repeat, you'll end up one roll short with a wall half-finished. Let's look at how to automate the calculation using JavaScript. The Math (Step-by-Step) Calculate the Drops Needed: Wall Width (inches) ÷ Roll Width (inches) = Number of Drops (Round up to the nearest whole number) Calculate the Cut Length: Wall Height (feet) + Pattern Repeat (feet) = Cut Length per Drop Calculate Drops per Roll: Roll Length (feet) ÷ Cut Length (feet) = Drops per Roll (Round down, because you can't use leftover scraps) Calculate Total Rolls: Total Drops Needed ÷ Drops per Roll = Total Rolls (Round up to the nearest whole roll) The JavaScript Solution Here is how you write a function to do this automatically, including converting the pattern repeat from inches to feet: function calculateWallpaper(wallWidthFt, wallHeightFt, rollWidthIn, rollLengthFt, patternRepeatIn) {
// 1. Total drops needed
const wallWidthIn = wallWidthFt * 12;
const dropsNeeded = Math.ceil(wallWidthIn / rollWidthIn);

// 2. Cut length per drop (wall height + pattern repeat)
const patternRepeatFt = patternRepeatIn / 12;
const cutLength = wallHeightFt + patternRepeatFt;

// 3. Drops per roll
const dropsPerRoll = Math.floor(rollLengthFt / cutLength);

// 4. Total rolls
if (dropsPerRoll === 0) {
throw new Error("The wall is too tall for this roll length.");
}

const totalRolls = Math.ceil(dropsNeeded / dropsPerRoll);

return {
dropsNeeded,
cutLength,
dropsPerRoll,
totalRolls
};
}

// Example: 10ft wide, 8ft high wall. 20.5in wide, 33ft long roll. 24in repeat.
const result = calculateWallpaper(10, 8, 20.5, 33, 24);
console.log(You need ${result.totalRolls} rolls.);
// Output: You need 2 rolls.
Common Gotchas Pattern Matching: If you have a "straight match" (like a checkerboard), you need exactly one full pattern repeat added to your cut length. If you have a "drop match" (like a diagonal pattern), you might need to add two repeats to alternate drops. Waste Factor: The Math.ceil() ensures you have enough rolls, but you should always buy one extra roll. It is much easier to return an unopened roll than to order more from the same dye lot later. Doors and Windows: If you have windows or doors, subtract their square footage from the total wall area before calculating drops to avoid buying too much paper. The Visual Way Trying to calculate drops, pattern repeats, and waste across multiple walls is a massive headache. If you want to determine the exact number of rolls required based on wall dimensions and pattern repeat drop distances, I built a free Wallpaper Roll Estimator. Try it here 100% client-side. Nothing uploaded. Have you ever underestimated a wallpaper project? Let me know in the comments.

Powered by Readybot.io

Calculate Wallpaper Rolls with JavaScript

Patungan: One-Transaction Group Payments on QIE

DEV Community

The last seat pays the seller: one transaction that swaps, seats and pays on QIE mainnet

Every group that books something together has one person who fronts the money. Picture Rina booking the Thursday 5-a-side football pitch: she pays the court, shares the cost in the group chat, then spends a week chasing people. If half the group drops out, she is the one who is short, and getting refunds back depends on her. Patungan is Indonesian for chipping in together. I built a contract that removes the person in the middle. Everyone pays their own seat into an escrow. The last seat pays the seller in that same transaction. If the deadline passes first, every member takes their money back. It is live on QIE mainnet: 0x2f4646D52a5393E239f5b880411dC2CA2D945F31, with source verified on Blockscout. Live app: patungan.edycu.dev · repo: github.com/edycutjong/patungan · no-wallet judge path: /judge The 2:41 demo, recorded against the live mainnet contract: This post is about the one transaction that makes it work, and the two walls I hit getting it onto mainnet. The rule: whoever fills the pool pays the seller The escrow logic is short. Every join ends in _seat. When the seat count reaches the target, the same call flips the pool to Paid and transfers the whole pot to the payee: function _seat(uint256 id, Pool storage p, address member, uint16 n, uint256 amount) private {
if (seatsOf[id][member] == 0) members[id].push(member);
seatsOf[id][member] += n;
paid[id][member] += amount;
p.filled += n;
p.held += uint128(amount);
totalHeld += amount;
if (p.filled == p.seats) {
uint256 total = p.held;
p.status = Status.Paid;
p.held = 0;
totalHeld -= total;
emit PoolPaid(id, p.payee, total);
qusdc.safeTransfer(p.payee, total); // the last seat pays the payee in the same transaction
}
}
There is no "release" button and no keeper. Nobody has to come back later to trigger the payout. The payee can be a .qie name from QIE's Zone naming contract. The contract resolves it when the pool is created and stores the owner address it found. If the name points somewhere other than the address the form showed, creation reverts with PayeeChanged. The hard part: the member holds QIE, the seller wants a stablecoin Pools are priced in QUSDC, so the seller knows exactly what they receive. But a member may hold only the native QIE token. Making them buy QUSDC on a DEX first, then approve, then join, is three steps before they can even take a seat. So joinWithQIE takes native QIE, buys exactly the QUSDC the seats cost (n × price) on QIEDEX, seats the member, and returns the unspent QIE, all in one call. If that member takes the last seat, the payout above runs in the same transaction too. The catch is that the QIEDEX router's source is not verified on the explorer. I am sending users' funds through a contract I cannot read. So the contract does not trust the router's quote. It checks it against the QIE Oracle: function _swapIn(uint256 amount) private returns (uint256 qieSpent, uint256 oraclePrice) {
uint256 fairQie;
(fairQie, oraclePrice) = _fairQie(amount);
uint256 ceiling = fairQie * (10_000 + maxDevBps) / 10_000;
address[] memory path = _path();
uint256 qieIn = router.getAmountsIn(amount, path)[0];
if (qieIn > ceiling) revert PriceDeviation(fairQie, qieIn);
if (msg.value < qieIn) revert ValueTooLow(qieIn, msg.value);

uint256 nativeBefore = address(this).balance;
uint256 qusdcBefore = qusdc.balanceOf(address(this));
router.swapETHForExactTokens{value: Math.min(msg.value, ceiling)}(amount, path, address(this), block.timestamp);
if (qusdc.balanceOf(address(this)) - qusdcBefore < amount) revert SwapShort();
qieSpent = nativeBefore - address(this).balance;
if (qieSpent > ceiling) revert PriceDeviation(fairQie, qieSpent);

}
Each check is there because of a specific way an untrusted router could cheat. Each one has a test with a hostile mock router: Before the swap: if the router's quote is above the Oracle's fair value plus th...

Powered by Readybot.io

Patungan: One-Transaction Group Payments on QIE

SSHole CVE-2026-123158: Check Alpine Servers Now

DEV Community

SSHole (CVE-2026-123158): Check Every Alpine Server and Image That Runs sshd

On November 9, 2026, CISA added CVE-2026-123158 to its Known Exploited Vulnerabilities catalog. The bug, nicknamed "SSHole", lets an attacker log in over SSH with a long junk password on some Linux systems that use the musl C library without PAM. Alpine Linux is the main example, and Alpine is a common base for Node.js containers and small cloud servers. Most SaaS teams on managed platforms will not be affected. Teams that run their own Alpine hosts, bastions or containers with an SSH server inside should check today, because exploitation started within hours of disclosure. What Happened OpenSSH released portable OpenSSH 10.6p2 on November 5 with what the project calls a critical security workaround. The release notes say sshd could be used to bypass password authentication on some Linux systems built and run with PAM disabled. The OpenSSH developers consider the root cause to lie outside sshd, but it is exploitable through sshd and is now blocked there. Alpine shipped patched packages the same day. Researchers' write-ups describe three choices that combine badly (OX Security's analysis): musl's crypt() rejects passwords longer than 256 bytes and returns . Linux uses * in /etc/shadow to mean "this account has no valid password". Since 2016, sshd hashes a password attempt using another account's hash settings when the target account has no usable hash, to make user enumeration harder. On an affected system, a password between roughly 256 and 1,024 characters makes the comparison * against , and the login succeeds. Alpine's tracker describes the same window: any password in that range succeeds for some account configurations. Help Net Security reported that the threat-intelligence firm Previdian saw a first attempt less than nine hours after the CVE was published, and that an Alpine honeypot gave the attacker root. The scale of exploitation beyond those reports is not public. The KEV listing confirms CISA has evidence of active exploitation. Who Is Affected According to the write-ups linked above, every one of these conditions must hold: sshd from OpenSSH before 10.6p2 runs on a musl-based Linux system (Alpine, OpenWrt, Buildroot, Yocto and images built from them); PAM is not used. Alpine's openssh-server package does not use PAM by default; password authentication is enabled, which is the OpenSSH default; at least one account has * in its password field (on Alpine, root has had * since about 3.16; key-only deploy users and LDAP users often do too); at least one other account on the same system has a real password hash. The reports single out Alpine cloud images on AWS and Azure. Their default alpine user is passwordless and can run doas without a password, so a login there can become root. The images are reported to become exploitable once any real password hash exists, for example after someone sets a console password. Not affected, per the same sources: glibc distributions such as Debian, Ubuntu, Fedora and RHEL, systems where sshd uses PAM, Dropbear, OpenBSD, accounts locked with !, and any system with PasswordAuthentication no. For a typical SaaS stack, that means: Vercel, Cloudflare Workers and similar platforms: you do not run sshd there, so there is nothing for you to patch (my inference; no provider has published a statement). Node.js containers on node:-alpine: the official images do not include an SSH server. You are exposed only if your Dockerfile adds openssh-server and starts it. Self-managed Alpine VMs, bastions and jump hosts: the highest-risk group. Check these first. GitHub-hosted Actions runners: these run Ubuntu, Windows or macOS, not musl. What to Do Today List hosts that accept SSH and run Alpine or another musl system. Include bastions, small utility VMs and anything built from an Alpine cloud image. Search infrastructure code for Alpine image IDs too. Search your Dockerfiles for an SSH server. Run grep -rniE "openssh|sshd" --include="Dockerfile" . across your repositories. For a built image, run d...

Powered by Readybot.io

SSHole CVE-2026-123158: Check Alpine Servers Now

Remove Forgotten PDF Passwords on Ubuntu/Linux

DEV Community

How to Remove Forgotten PDF Password Protection in Ubuntu/Linux

How to Remove Forgotten PDF Password Protection in Ubuntu/Linux Getting locked out of your own important PDF document is frustrating—especially when you need to print, edit, or extract data from it right away. Fortunately, Ubuntu and other Linux distributions offer a powerful suite of open-source command-line tools that let you inspect PDF encryption, recover a forgotten password for your own files, and generate a permanent, unlocked copy. In this step-by-step guide, we will walk through the exact workflow using native Linux utilities. Tools We Will Use Before diving into the commands, here is a quick overview of the toolkit we are going to install: qpdf: Inspects PDF encryption details and decrypts files once authorized credentials are available. John the Ripper: A widely used password-auditing tool capable of recovering forgotten PDF passwords. pdf2john: A utility script that extracts password hashes from encrypted PDFs so John the Ripper can analyze them. PDFtk: A versatile toolkit for manipulating, merging, and decrypting PDF documents. Poppler Utilities (poppler-utils): A collection of tools (pdfinfo, pdftotext, etc.) used to inspect metadata and extract content. Understanding PDF Password Protection Not all PDF locks work the same way. PDF documents generally support two distinct types of password protection: Password Type Description User Password (Open Password) Required just to open and read the contents of the PDF. Owner Password (Permissions Password) Allows anyone to view the document, but restricts actions like printing, editing, or copying text. Important Distinction: If your PDF opens normally without a prompt but blocks you from printing or copying text, it has owner-password protection. If a dialog box asks for a password before displaying the pages, it has open-password protection. Step 1: Update Ubuntu and Install Required Applications First, open your terminal (Ctrl + Alt + T) and update your system's package repositories to ensure you get the latest versions of the tools: sudo apt update && sudo apt upgrade -y

Next, install all the required PDF utilities in one command: sudo apt install qpdf pdftk-java john poppler-utils -y

Verify that every application was installed properly by checking their version numbers: qpdf --version
pdftk --version
john --version
pdfinfo -v

Step 2: Inspect the PDF Encryption Navigate to the folder where your locked PDF is stored (for example, your Downloads directory) and make a backup copy before making any changes: cd ~/Downloads
cp protected.pdf protected_backup.pdf

Run qpdf to inspect the document's encryption settings: qpdf --show-encryption protected.pdf

You can also inspect the document's metadata using pdfinfo: pdfinfo protected.pdf

Look closely at the Encrypted field in the terminal output. To quickly verify whether the file blocks reading without a password, test extracting text to standard output: pdftotext protected.pdf -

If the terminal prompts you for a password or throws an authentication error, the file has open-password protection. Step 3: Handle Owner-Password Protection If your PDF opens normally in a viewer but restricts printing, copying, or editing, inspect its permissions first: qpdf --show-encryption protected.pdf

If you have the necessary authorization and the document permits access without an open password, you can often generate an unrestricted copy directly with qpdf: qpdf --decrypt protected.pdf unlocked.pdf

Verify that the newly created file is structurally sound: qpdf --check unlocked.pdf

(Note: If the file enforces an owner password that requires credentials you do not have, --decrypt alone will not bypass it.) Step 4: Recover a Forgotten Open Password If your PDF requires a password just to open, you will need to recover the password first using John the Ripper. 1. Locate the pdf2john Extraction Utility Search your system to find where the pdf2john script is located: find /usr -name 'pdf2john*' 2>/dev/null

(Depending on y...

Powered by Readybot.io

Remove Forgotten PDF Passwords on Ubuntu/Linux

6 Blacksmith Alternatives for GitHub Actions Ranked

DEV Community

Blacksmith alternatives for GitHub Actions, priced and ranked

The Blacksmith alternatives GitHub Actions teams shortlist are the six other vendors that answer a runs-on label, and they are ranked here by the Linux rate each one published on 2026-09-20 at 2 vCPU. Blacksmith itself sits mid-table at $0.004 for Ubuntu x64 and $0.0025 for ARM, so the question is never only price: it is whether you are leaving for the rate, for a billing model Blacksmith does not publish, or for an operating system it charges a premium on. The same 10,000 Linux minutes at 2 vCPU on each vendor, at the rates published on 2026-09-20, with monthly plan fees inside the bar. Blacksmith x64 lands at $28. GitHub-hosted Team is $42, the $60 list price less the $18 of included usage the Team plan carries. Blacksmith is a genuinely good product and the honest starting point is what it does well. Its pitch, in its own words rather than any benchmark run here, is a high single-core clock on its own metal: the buy when one compile or bundle step is your critical path. It includes 3,000 free minutes a month on every plan card, the most generous standing allowance here. Its ARM card at $0.0025 undercuts every other ARM rate here except Namespace at $0.002, and buys 6 GB at 2 vCPU: Blacksmith publishes arm64 at 3 GB per vCPU, so there is no 8 GB ARM card. The three reasons teams look past it are specific. Ubuntu x64 at $0.004 a minute is mid-table now rather than cheap. Docker layer caching and sticky disks are add-ons at $0.50 per GB per month rather than included, so the effective rate for a Docker-heavy pipeline is above the card. And billing granularity is published nowhere, on the pricing page or in the docs, which is the row that decides a wide matrix of short jobs. The ranking criterion below is the published Linux x64 rate at 2 vCPU for a private repository, read on 2026-09-20, with the memory that rate buys next to it. Every alternative here is a runs-on label change, so the cost of getting this wrong is a revert commit. Every alternative, ranked by published Linux rate A shortlist, not the field: Blacksmith itself and the four its users move to. Ubicloud for the rate, Namespace for cores per dollar, Latchkey for re-run waste, Depot for a Docker cache included rather than billed per GB. WarpBuild and RunsOn are in the next table, and all eight are priced side by side in the roundup. Against each vendor's cheapest card, Blacksmith ARM at $0.0025 is joint third here and its x64 at $0.004 fourth. Vendor Linux, 2 vCPU Linux, 4 vCPU Free tier Billing granularity Best for Ubicloud $0.0012 standard, $0.0020 premium (8 GB) $0.0025 standard, $0.0040 premium 1,250 min/month Not published Leaving Blacksmith purely on rate Namespace $0.002 prepaid at 4 GB, $0.004 at 8 GB $0.004 prepaid at 8 GB 30-day trial only Unit minutes, prepaid or overage Leaving for twice the cores at 8 GB Latchkey $0.0025 (8 GB) $0.005 (16 GB) 2,000 to 6,000 min/month Per minute Leaving because re-runs are a real cost Blacksmith $0.0025 ARM, $0.004 Ubuntu x64 $0.005 ARM, $0.008 Ubuntu x64 3,000 min/month Not published Staying: a compile-bound critical path Depot $0.006 (8 GB) $0.012 (16 GB) 2,000 min on the $20/mo plan Tracked per second, billed monthly in whole minutes Leaving for Docker builds and a big cache What each alternative has that Blacksmith does not The rate is one column of eleven. These are the rest, written against Blacksmith, with the full eight-vendor matrix in GitHub Actions runner alternatives. Vendor Against Blacksmith on rate What it adds What it gives up Ubicloud 70% under x64, 52% under ARM 1,250 free min/mo and 30 GB of cache included rather than metered Windows, macOS and any ARM card at all; Linux x64 only, to 16 vCPU Namespace Level at 8 GB, 50% under at 4 GB Twice the cores at the same 8 GB and the same rate, and remote Docker builders Any standing free allowance; cache is billed at $0.0048/GB-day WarpBuild Level managed, 50% under on BYOC Runners executing inside your own AWS, GCP or Azure account, add-ons free Capacity p...

Powered by Readybot.io

6 Blacksmith Alternatives for GitHub Actions Ranked

Fix GitHub Actions pwsh Not Found on Ubuntu

DEV Community

GitHub Actions pwsh command not found on an Ubuntu runner

GitHub Actions pwsh command not found is raised while the runner is looking for the shell binary, which is before your script has been started and before any process could have exited. That ordering is the useful part: there is no exit code attached to this failure, so an answer that tells you to go and read one is describing a different problem. Shell resolution happens before the script file is written. A failure here means no process was started, so no exit code exists. What this error means A step that declares the PowerShell Core shell fails immediately, with a short line naming the command. Steps around it that use the default shell run normally, which makes the runner look selectively broken. On a GitHub hosted Ubuntu image this is rare because those images ship the shell. On a self hosted runner, a container image built in house or a runner in a minimal base image, it is the expected result of asking for a program that was never installed. ```Reconstructed from the FileNotFoundException message in WhichUtil.Which, actions/runner pwsh: command not found

Common causes

The runner image does not include PowerShell Core

The direct cause in almost every report. Self hosted machines, container images and minimal bases install what the build needs, and a shell nobody asked for at image build time is not there at job time.

The step was copied from a Windows job

A workflow that grew a Linux matrix leg keeps the shell declaration that made sense on Windows. The step is often small enough that the shell is not really needed at all.

The job runs in a container that differs from the host

A step running inside a container is looked up differently from one running on the host, and a shell present on the machine is not necessarily present in the image the job is using.

The shell string is custom and names a program that is absent

A shell value with arguments is parsed into a command and a format, and the command is looked up like any other. In our experience this version is harder to spot because the eye reads the whole string as configuration rather than as a program name.

How to fix it

Check for an exit code before anything else

  1. Look at the failing step for an exit status line.
  2. If there is one, this page is not your failure; the script started and something inside it was missing.
  3. If there is none and the line is just the command name, the runner could not find the shell.

Use the default shell when the script is small

Drop the shell declaration and translate the commands. On Linux the runner resolves the default by looking for one shell and falling back to another, so you do not need to name anything.

```.github/workflows/ci.yml
- name: Print the version
run: |
node -p "require('./package.json').version"
Install the shell in the image, not in the job Add it where the runner image is built so every job starts with it present. Installing it as a step costs time on every run and turns a clear failure into a network dependent one. Probe for the program and fail with a useful message Where you cannot control every runner, check for the program in an early step and say what is missing. A named assumption is easier to act on than a lookup failure in the middle of a matrix. - name: Preflight
run: |
command -v pwsh >/dev/null || {
echo "this job needs PowerShell Core on the runner"; exit 1; }
How to prevent it Keep the shell values in a workflow to programs the runner image is known to ship. Install shells at image build time, never as a workflow step. Probe for unusual programs in one preflight step rather than discovering them mid matrix. When adding a Linux leg to a Windows matrix, review every shell declaration. Where the message comes from, and what it rules out Before a run step executes, the runner has to decide which program will execute it. For a step that names one of the built in shells it looks that program up on the path, with a flag that says the lo...

Powered by Readybot.io

Fix GitHub Actions pwsh Not Found on Ubuntu

** Latest from PC Gamer **

The most annoying questgivers in PC games

The XP isn't worth it.

Powered by Readybot.io

** Latest from PC Gamer ** ## The most annoying …

** Latest from PC Gamer **

GTA 6 soundtrack leak confirmed accurate with new songs from Lana Del Rey, Playboi Carti, and Keith Richards

What, no Sideways Hank O'Mally?

Powered by Readybot.io

** Latest from PC Gamer ** ## GTA 6 soundtrack leak confirme

GameSpot - All Content

GTA 6 Is Like The Olympics – “A Rare Cultural Moment” With Massive Ripple Effects

After years of development, multiple delays, and what can only be assumed to be one of the biggest production budgets ever, Rockstar's Grand Theft Auto 6 launches on November 19. The game is poised to "blot out the sun," some experts believe, and its release looms so large that other gaming companies are shifting dates for their own games to stay out of the blast radius. Francis Lawrence, the director of the new Hunger Games movie Sunrise on the Reaping, which comes out a day after GTA 6, has said he hopes people can find the time to play the game and watch his movie. In short, GTA 6 is seen by some as a black hole that will suck up time, attention, and money from the broader gaming economy--and even workplaces, as people dive into the 80-hour game they've been waiting a decade to play. To help make sense of, and contextualize, the enormity of GTA 6's looming launch, GameSpot caught up with Bart Spiegel of the global professional services and research company PricewaterhouseCoopers, or PwC. He told GameSpot that GTA 6 is "something much bigger than a traditional entertainment launch," and is more akin to an event like the Olympics. He believes GTA 6 is a "rare cultural moment" that "commands extraordinary attention and creates economic activity well beyond the event itself." Jason pumping some iron in GTA 6. Spiegel said he foresees potential shifts beyond gaming, in places like TV viewership, music consumption, social media engagement, and even travel. "In an increasingly fragmented entertainment landscape, it's rare for a single release to command this much attention across so many industries simultaneously. That's what makes this moment so significant," he said. An economics professor recently claimed that about 1.5 million people plan to "call out sick" to play GTA 6, and this could come at a "cost" of $1 billion to the US economy. Spiegel said people should remember that GTA 6 isn't anything new or special as it relates to taking time off work. "People regularly plan time off around major cultural and entertainment events, and this is another example of consumers prioritizing an experience they're excited about," he said. That being said, Spiegel remarked that PwC has observed estimates suggesting time-off requests near GTA 6's release could be 9% to 17% higher than normal. "But what's more interesting to me is what happens outside the workplace. If millions of people are spending additional hours gaming, they're potentially spending less time watching television, going out to restaurants, or engaging in other activities," he said. "And unlike a sporting event that lasts a few hours or a few weeks, this experience could keep people engaged for months. So the broader economic implications may extend well beyond a single day of missed work," he added. "Huge net positive" GTA 6 is expected to be an enormous success commercially--it's reportedly already sold 11 million units through pre-purchases, and that could rise to 25 million at launch. That would work out to $2 billion in revenue, which would cover the game's entire development budget and most of its marketing spend, Sensor Tower said. But many are also saying that GTA 6 represents the last of a dying breed, and that other publishers might learn all the wrong lessons from its success. Spiegel said GTA 6 is going to be a "huge net positive for the gaming industry as a whole," in part because its success will reiterate to the broader entertainment and media landscape that games are culturally significant. At the same time, Spiegel said he doesn't foresee a world in which other publishers try to replicate a blockbuster of this magnitude. "Very few organizations have the capital, expertise, and intellectual property required to support investments on this scale. These are extraordinary events, not necessarily repeatable business models," Spiegel said. If GTA 6 is the huge success it's projected to be, it could positively uplift the broader gaming ecosystem in a lot of w...

Powered by Readybot.io

**GameSpot - All Content** ## GTA 6 Is Like The …

IGN India Pc

League of Legends: New Dawn - Official Teaser Trailer

Check out the latest teaser for League of Legends: New Dawn as the team shares a sneak peek at what's coming in 2027. A full reveal is scheduled for January, with the release planned for later in the year.

Powered by Readybot.io

**IGN India Pc** ## League of Legends: New Dawn - Official T

** Latest from PC Gamer **

Planeswalker, Netflix's Magic: The Gathering animated series, will have a different art style for each plane

"Each one of these cards is this window into this incredible world. It's not just world building—it's worlds building."

Powered by Readybot.io

** Latest from PC Gamer ** ## Planeswalker, Netflix's Magic:

IGN India Pc

Slay the Spire 2's New Character is Wild - The Fool Starter Guide

The first brand new Slay the Spire 2 character since the early access launch is finally here! Its name is The Fool, and it's one of the most interesting concepts for a Slay the Spire 2 character yet. In this quick Starter Guide for The Fool, we'll touch upon his unique mechanics, some standout cards, and a few deckbuilding tips to get you started on the right foot.

Powered by Readybot.io

**IGN India Pc** ## Slay the Spire 2's New Character …

IGN India Pc

League of Legends: New Dawn Cinematic Images


Powered by Readybot.io

**IGN India Pc** ## League of Legends: New Dawn Cinematic Im

IGN India Pc

League of Legends: New Dawn Gameplay Images


Powered by Readybot.io

**IGN India Pc** ## League of Legends: New Dawn Gameplay Ima

IGN India Pc

League of Legends: New Dawn Unveiled With Debut Trailer, Riot Announces Major Overhaul Coming in 2027

Rift apart. At the 2026 League of Legends World Championship Finals, Riot Games officially unveiled League of Legends: New Dawn. The large-scale update is scheduled for 2027 and will bring changes to the game's client, Summoner's Rift, visuals, and gameplay, marking the beginning of a new chapter for one of the industry's …

Powered by Readybot.io

**IGN India Pc** ## League of Legends: New Dawn Unveiled …

** Latest from PC Gamer **

WoW: Forever dungeon mobs no longer give EXP if they're trivial for anyone in the party

No more calling on your high-level buddy for a boost.

Powered by Readybot.io

** Latest from PC Gamer ** ## WoW: Forever dungeon mobs no l

IGN India Pc

Resident Evil Requiem Star Hopes Grace Ashcroft Has 'a Long Way to Go' Even if She Won't 'Ever Be a Leon Character'

"She's never going to be badass, you know, doing roundhouse kicks." Grace Ashcroft actress Angela Sant'Albano doesn't think her Resident Evil Requiem hero will "ever be a Leon character," but she's still hoping "there's a long way to go with her." The person behind one of 2026's standout video game roles laid out her hopes for the future during an interview …

Powered by Readybot.io

**IGN India Pc** ## Resident Evil Requiem Star Hopes Grace …

** Latest from PC Gamer **

Is the game funny, or just the players? Jackbox CEO says they get 'a lot of false positives' with a staff of comedy writers

Testing comedy games comes with a unique challenge.

Powered by Readybot.io

** Latest from PC Gamer ** ## Is the game funny, or just the