Om ActiQs
ActiQs hjälper dig att läsa information om ingredienser, produktdeklarationer och forskning. Här kan du följa en produktuppgift till en ämnespost och vidare till det underlag som används i en text. [ACTIQS-METHOD]
Separat granskad . Källornas egna datum framgår av underlagen.
Vad ActiQs hjälper dig att läsa
En produktdeklaration visar vad källan deklarerar. Den visar inte laboratorieverifierat innehåll eller att produkten har den effekt som undersökts i en viss studie. En bibliografisk sökträff hjälper dig att hitta en publikation; träffen är inte i sig ett effektbevis. [ACTIQS-METHOD]
ActiQs katalogiserar information och säljer inte produkterna. En produktlänk i ett läsområde är en väg till en deklaration, ingen rekommendation att köpa eller använda produkten. [ACTIQS-METHOD]
Huvudman
Nutri Nordic AB är huvudman och personuppgiftsansvarig för ActiQs. Företaget ansvarar även för drift- och säkerhetsincidenter. [ACTIQS-OWNER]
Kontakt och rättelser
Den planerade kontaktadressen för frågor och rättelser är hello@actiqs.com. Brevlådan är ännu inte upprättad. Beskriv vilken sida och uppgift ditt ärende gäller. Skicka inte privata hälsouppgifter. [ACTIQS-OWNER] [ACTIQS-OWNER-CONTACT-STATUS]
Så granskas områdestexter och guider
De svenska områdestexterna och guiderna i läspaketet går genom separat AI-granskning av den exakta hela textversionen mot det tilldelade källunderlaget. Kontrollen omfattar också hänvisningarna och de synliga sammanfattande delarna. Därefter gör författaren en slutkontroll mot samma text och underlag före publicering. [ACTIQS-PROCESS]
”Separat granskad” ska läsas i den betydelsen. Det är inte ett intyg om granskning av en medicinsk specialist, och granskningen gör inte en osäker studie säker. Den kan inte heller ersätta personlig vård eller rådgivning. [ACTIQS-PROCESS] [NCCIH-TEN-FACTS]
Läs källornas avgränsning och datum
Hänvisningarna i en områdestext eller guide leder till sidans källpaneler. Där visas det tilldelade underlaget, länken till källan och en beskrivning av vad som ingår när en sådan avgränsning finns. Läs avgränsningen: ett faktablad är inte alla studier som faktabladet hänvisar till, och en återgiven produktdel är inte en ny analys av produkten. [ACTIQS-PROCESS] [NCCIH-TEN-FACTS]
Textens granskningsdatum och originalets egna datum har olika betydelse. Ett nytt granskningsdatum betyder inte att en gammal studie är ny eller att produktens uppgifter nyss har hämtats från återförsäljaren. [ACTIQS-PROCESS] [NCCIH-TEN-FACTS]
Så gör du ett rättelseunderlag användbart
Ange sidans adress, vilken mening eller tabellrad det gäller och vad du jämför den med. Bifoga originalets adress och uppgift om rättelse eller version om det finns. Beskriv först det du ser och därefter din föreslagna rättelse. [ACTIQS-METHOD] [ACTIQS-PROCESS]
Behåll skillnaden mellan saknad och noll, mellan deklarerad uppgift och uppmätt resultat samt mellan preliminär forskning och etablerad kunskap. Skicka inte privata hälsouppgifter för att förklara en avvikelse i en offentlig text. [ACTIQS-METHOD] [NCCIH-TEN-FACTS]
En ändrad områdestext eller guide behöver granskas som en ny exakt helversion före publicering. En tidigare granskning får inte användas som godkännande av en annan text eller ett annat tilldelat underlag. [ACTIQS-PROCESS]
Bilder och krediter
Artikelbilderna märks som illustrationsbilder och visar fotografens kredit och bildtjänsten. En illustration är inte dokumentation av deltagare, produkt eller försöksutrustning i den återgivna studien. Läs originalet för studiens egna bilder och uppgifter. [ACTIQS-PROCESS]
Att ta med
- Planerad kontakt och rättelser: hello@actiqs.com. Brevlådan är ännu inte upprättad. [ACTIQS-OWNER] [ACTIQS-OWNER-CONTACT-STATUS]
- Huvudman, personuppgiftsansvarig och incidentansvarig: Nutri Nordic AB. [ACTIQS-OWNER]
Källor och hela underlag
ACTIQS-METHOD · ActiQs
Two complete editorial prose sections and whole limitations/no-sales sidebar, anonymously read through browser. Source directory excluded; whole current procedural description, not clinical evidence.
URL: https://www.actiqs.com/sv/metod Publisher: ActiQs Source date: Not independently established; capture date is not publication date Captured: 2026-10-18T18:42:30.088Z Scope: Two complete editorial prose sections and whole limitations/no-sales sidebar, anonymously read through browser. Source directory excluded; whole current procedural description, not clinical evidence. Capture: Actual anonymous browser DOM; direct requests429, no documentHTTP200 or rawHTML claimed Läs om ämnen och deklarationer Följ granskade områdestexter, guider och deras källor. Till läspaketet → Vad den första versionen innehåller Ingrediensregistret innehåller korta egna grundbeskrivningar med referenser till NIH Office of Dietary Supplements. Produktregistret visar importerade produkter från Open Food Facts med ursprunglig ingredienstext, näringsfält och klickbara källkoder. Uppgifterna är användarbidrag och kan vara ofullständiga. Separata, tydligt märkta fiktiva exempel används för mängdjämförelser. Publikationsregistret hämtar bibliografisk metadata från Europe PMC. En automatisk sökträff är bibliografisk metadata och används inte som bevis för en ingrediens effekt. Tre skillnader som alltid ska synas En deklarerad mängd är inte ett laboratorieverifierat innehåll. Okänd mängd är inte noll. Saknad interaktionspost är inte ett säkerhetsbesked. Forskning och hälsopåståenden ActiQs ska beskriva källor och deras begränsningar. Att citera en annan aktör är inte ett generellt undantag från regler om hälsopåståenden. Den som återanvänder data i produktmarknadsföring behöver bedöma den konkreta användningen. Livsmedelsverkets vägledning om närings- och hälsopåståenden → Rättigheter till data Registret sparar en rättighetsuppgift per källa. Grundbeskrivningar är egna sammanfattningar; referenslänkar är inte tillstånd att återpublicera originaltexter eller bilder. Import av nya produktdatabaser behöver en bedömning av villkor för vidareleverans. Under uppbyggnad Täckningen är begränsad. Den här versionen är avsedd för granskning och utveckling och är inte ett komplett ingrediens- eller säkerhetsregister. Ingen produktförsäljning ActiQs katalogiserar information. Sajten har ingen varukorg, inga produktköp och ingen försäljningsrankning.
NCCIH-TEN-FACTS · NIH National Center for Complementary and Integrative Health
Whole main including introduction and all ten numbered facts via officialwebreader14..31. Sitefooter18October2026 is not an article update; linked originals not independently read.
URL: https://www.nccih.nih.gov/health/tips/10-things-to-know-about-the-science-of-health Publisher: NIH National Center for Complementary and Integrative Health Source date: Not independently established; sitefooter is not article date Captured: 2026-10-18T18:00:36.954872+00:00 Scope: Whole main including introduction and all ten numbered facts via officialwebreader14..31. Sitefooter18October2026 is not an article update; linked originals not independently read. Capture: official web reader; no direct rawHTML/PDFhash orHTTP200 claimed # 10 Things To Know About the Science of Health It’s sometimes difficult to tell the difference between health facts and myths, particularly around complementary and integrative health. Becoming familiar with scientific topics related to health research can help you better understand what you hear and read and make well-informed health decisions. These 10 facts can give you a start in learning about the science of health. Want to know more? Check out our Know the Science online toolkit. 1. Some online sources of information on complementary health approaches are useful, but others are inaccurate or misleading. If you're visiting an online health site for the first time or downloading a new app, ask these questions: Who runs or created the site or app? Do its claims seem too good to be true? Is it up-to-date? Where does the information come from? Why does the site or app exist? Is it selling something? 2. Unless you read and understand the original sources for a health news story, it can be difficult to know whether the story is misleading or has left out important information. But the likelihood that the story is correct increases if it comes from a media outlet that isn’t promoting a point of view or cause, was written by a trained science or health reporter, and includes quotes from experts not connected to the study. 3. Sometimes taking a prescription drug and dietary supplement together may increase the drug’s effects. The drug’s effects may become too strong, and unwanted side effects may increase. 4. Sometimes taking a prescription drug and a supplement together may decrease the drug’s effects. This means that you aren’t getting the full benefit from the drug that your health care provider wants you to have. 5. When it comes to medicine, there is no official definition for use of the term natural. And it’s important to know that “natural” does not always mean “safe.” 6. Although many herbal or dietary supplements (and some prescription drugs) come from natural sources, “natural” does not always mean that it’s a better option for your health. Scientists are studying many of these products to identify what ingredients may be active and to better understand their effects in the body. 7. Clinical trials to test whether a treatment is useful and safe in humans may vary in size and type. Well-planned clinical trials give the clearest information about whether a treatment is effective and safe. However, because they’re complicated, lengthy, and very, very expensive, they’re usually done only after smaller preliminary studies have shown some promise that the treatment may be helpful. 8. The number of people participating in a study can affect the outcome of the study and what the results mean. Larger studies can increase the accuracy of the study findings and reduce the probability that any effect observed in the study was due to chance. 9. The strongest evidence about whether a treatment is useful and safe consists of results from several studies by different investigators. Rarely does a single study provide a final, definitive answer. 10. When looking for information from a study published in a medical journal, look at the date of the study. Was it conducted in the past year? 5 years? 15 years? As new information is learned, scientific standards and techniques change, and practices evolve. Looking at the date can provide insight into how the study fits into the larger evidence base on a particular topic.
ACTIQS-PROCESS · ActiQs
ActiQs eget processunderlag: sju hela implementationsoriginal från angiven daterad webbversion. Ingen klinisk källa, ingen hämtad myndighetssida och ingen publik originaladress. Hela originalet återges här.
{
"contract": "visitor-content-first-party-originals-v1-20261019",
"publisher": "ActiQs",
"origin_kind": "implementation_snapshot",
"claims_scope": "publisher_process_and_responsibility_only",
"recorded_at": "2026-10-19T07:43:09.003572+00:00",
"provenance": {
"bundle_sha256": "f57ba0c07cb0ff811b2dcbd8bfe408cc376db03969dcdd1980840456b09a8a26",
"freeze_sha256": "25208267b37dfef4c46bbf1fe56d29af3ed2551f7cefc2f11d8c715cc9752072",
"files": [
{
"path": "src/lib/visitor-publications.ts",
"text": "import{createHash}from'node:crypto';\nimport{cache}from'react';\nimport{validateGuideRequest}from'./visitor-guides/review-request';\nimport{verifyGuideAttempt}from'./visitor-guides/exact-attempt-verifier.mjs';\nimport{asyncProductGuideSourcesMatch}from'./visitor-guides/async-product-source-guard';\nimport bundle from'../data/visitor-publications.json';\nimport type{Database}from'./database';\nconst hash=(v:string)=>createHash('sha256').update(v).digest('hex');\nfunction need(v:unknown,message:string):asserts v{if(!v)throw Error(message);}\nexport type VisitorPublication={job:any;attempt:any;journal:any;started:any;author_final:{draft_sha256:string;source_book_sha256:string;checked_at:string;author_identity:string}};\n/** Reads exported actual ledger rows. No input is allowed to supply an inferred approval. */\nexport function verifyVisitorPublication(p:VisitorPublication){\n const{job,attempt,journal,started,author_final:final}=p;\n need(job&&attempt&&journal&&started&&final,'Missing publication origin');\n need(job.id==='visitor-guide:'+hash(job.draft_text+'\\0'+job.source_book_text),'Job identity does not bind exact bytes');\n need(job.state==='ready'&&attempt.job_id===job.id&&attempt.attempt===job.attempts&&journal.id===job.id&&journal.attempt===job.attempts,'Wrong approved attempt');\n need(journal.response_json&&journal.received_at&&journal.dispatch_started_at,'No completed actual response');\n need(journal.owner===started.owner&&journal.token===started.lease_token,'Claim/journal owner mismatch');\n const start=Date.parse(journal.dispatch_started_at),end=Date.parse(journal.received_at),lease=Date.parse(started.lease_until);\n need(Number.isFinite(start)&&Number.isFinite(end)&&Number.isFinite(lease)&&end>=start&&end<lease,'Actual response outside claim lease');\n need(attempt.reviewer_identity===journal.owner&&attempt.model===journal.requested_model&&attempt.started_at===journal.dispatch_started_at&&attempt.finished_at===journal.received_at,'Attempt does not bind actual request');\n need(hash(journal.request_json)===journal.request_sha256,'Recorded request changed');\n const request=JSON.parse(journal.request_json),response=JSON.parse(journal.response_json);validateGuideRequest(request,job);\n need(response.representation==='choice-message-content'&&response.finish_reason!=='length'&&response.requested_model===journal.requested_model&&response.raw_response===attempt.raw_response&&response.raw_response_sha256===attempt.raw_response_sha256&&hash(response.raw_response)===response.raw_response_sha256,'Recorded response mismatch');\n const review=verifyGuideAttempt({draftBytes:Buffer.from(job.draft_text),sourceBookBytes:Buffer.from(job.source_book_text),job,attempt});\n need(final.author_identity===job.author_identity&&final.draft_sha256===job.draft_sha256&&final.source_book_sha256===job.source_book_sha256&&Number.isFinite(Date.parse(final.checked_at))&&Date.parse(final.checked_at)>=end,'Missing exact whole author final after review');\n const draft=JSON.parse(job.draft_text),book=JSON.parse(job.source_book_text);\n need(draft.schema_version===1&&draft.language==='sv'&&/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(draft.id)&&['area','guide'].includes(draft.content_kind??'guide'),'Unsupported published content');\n need(draft.source_book_sha256===job.source_book_sha256,'Source book binding mismatch');\n need(Array.isArray(book.sources)&&book.sources.length===draft.sources.length,'Incomplete originals');\n for(const s of book.sources)need(Array.isArray(s.original_sections)&&s.original_sections.length&&hash(JSON.stringify(s.original_sections))===s.captured_sections_sha256&&/^https:\\/\\//.test(s.source_url),'Invalid original or public source link');\n return{draft,book,review};\n}\n/** Only deployment-bundled, independently approved, still-current originals become public. */\nexport async function publishedVisitorContent(db:Database,areaIdentity?:string){\n const result=[];\n for(const raw of bundle.entries as VisitorPublication[]){\n // A navigation filter only; every selected entry still requires exact approval and current sources.\n if(areaIdentity){const draft=JSON.parse(raw.job.draft_text);if(draft.content_kind!=='area'||!draft.identity_ids?.includes(areaIdentity))continue;}\n const checked=verifyVisitorPublication(raw);\n if(!await asyncProductGuideSourcesMatch(db,raw.job))continue;\n result.push(checked);\n }\n return result;\n}\nexport const visitorPublicationList=cache(async()=>{\n if(!bundle.entries.length)return[];\n const{database}=await import('./database');return publishedVisitorContent(await database());\n});\nexport async function visitorPublication(kind:'area'|'guide',id:string){return(await visitorPublicationList()).find(p=>(p.draft.content_kind??'guide')===kind&&p.draft.id===id)??null;}\nexport async function publishedVisitorProducts(){\n const candidates=bundle.products as{ id:string;record_id:string;version_id:string;name:string;ean13:string;hosted_verified_at:string }[];\n if(!candidates.length)return[];\n const{database}=await import('./database'),db=await database();\n const rows=await db.query<{id:string;current_version_id:string}>('SELECT id,current_version_id FROM retailer_product_records WHERE id IN ('+candidates.map(()=>'?').join(',')+')',candidates.map(p=>p.record_id));\n return candidates.filter(p=>Number.isFinite(Date.parse(p.hosted_verified_at))&&rows.some(r=>r.id===p.record_id&&r.current_version_id===p.version_id));\n}\n",
"sha256": "90880e97f8c9caec3027290b83bb2501b362e7d664e7bbcff1f6e6db280ba464",
"bytes": 5385
},
{
"path": "src/lib/visitor-guides/exact-attempt-verifier.mjs",
"text": "// Isolated exact-attempt verifier. No worker, database, model call or publication integration.\r\nimport {hash} from './guide-reader.mjs';\r\nimport {visibleBlocks} from './visible-coverage.mjs';\r\nconst requireValue=(v,m)=>{if(!v)throw Error(m);};\r\nexport function verifyGuideAttempt({draftBytes,sourceBookBytes,job,attempt}){\r\n requireValue(job&&attempt&&job.id===attempt.job_id,'Attempt/job mismatch');\r\n requireValue(job.state==='ready'&&Number.isSafeInteger(job.attempts)&&job.attempts>0&&attempt.attempt===job.attempts,'No current ready attempt');\r\n requireValue(attempt.outcome==='approved'&&attempt.started_at&&attempt.finished_at,'No finished approved attempt');\r\n const started=Date.parse(attempt.started_at),finished=Date.parse(attempt.finished_at);\r\n requireValue(Number.isFinite(started)&&Number.isFinite(finished)&&finished>=started,'Invalid attempt dates');\r\n requireValue(job.author_identity&&attempt.reviewer_identity&&job.author_identity!==attempt.reviewer_identity,'Separate reviewer required');\r\n requireValue(typeof attempt.model==='string'&&attempt.model.trim(),'Missing actual review model');\r\n const draftHash=hash(draftBytes),bookHash=hash(sourceBookBytes);\r\n requireValue(job.draft_sha256===draftHash&&attempt.draft_sha256===draftHash&&job.source_book_sha256===bookHash&&attempt.source_book_sha256===bookHash,'Exact input binding failed');\r\n requireValue(typeof attempt.raw_response==='string'&&attempt.raw_response.length>0&&hash(attempt.raw_response)===attempt.raw_response_sha256,'Raw response binding failed');\r\n const response=JSON.parse(attempt.raw_response);\r\n requireValue(response.decision==='approve'&&response.complete===true&&response.identity_preserved===true&&response.sources_supported===true&&response.no_unsupported_claims===true,'No complete semantic approval');\r\n requireValue(typeof response.confidence==='number'&&Number.isFinite(response.confidence)&&response.confidence>=.95&&response.confidence<=1,'Approval confidence insufficient');\r\n requireValue(typeof response.reason==='string'&&response.reason.trim(),'Missing actual reason');\r\n requireValue(!/\\b(?:reject|rejected|do not approve|cannot approve)\\b/i.test(response.reason),'Contradictory approval reason');\r\n requireValue(Array.isArray(response.findings)&&response.findings.length===0,'Unresolved findings');\r\n const draft=JSON.parse(draftBytes.toString('utf8')),blocks=visibleBlocks(draft),sources=new Set(draft.sources.map(s=>s.id));\r\n requireValue(response.visible_coverage_contract==='whole-visible-guide-v1'&&Array.isArray(response.visible_coverage)&&response.visible_coverage.length===blocks.length,'Incomplete visible review');\r\n for(const block of blocks){const matches=response.visible_coverage.filter(c=>c.block_id===block.id);requireValue(matches.length===1,'Missing/duplicate visible review');const c=matches[0];requireValue(c.supported===true&&c.text_sha256===block.text_sha256,'Unsupported/changed visible block');requireValue(Array.isArray(c.source_ids)&&c.source_ids.length>0&&new Set(c.source_ids).size===c.source_ids.length&&c.source_ids.every(id=>sources.has(id)),'Invalid visible source references');}\r\n return {draft_sha256:draftHash,source_book_sha256:bookHash,actual_response_sha256:attempt.raw_response_sha256,finished_at:attempt.finished_at,author_identity:job.author_identity,reviewer_identity:attempt.reviewer_identity,model:attempt.model,visible_coverage:response.visible_coverage,decision:'approve'};\r\n}\r\n",
"sha256": "3d4eff1acf158fbeb5231e79ac40c9413c7423ed32b935628ca9be034cca6900",
"bytes": 3436
},
{
"path": "src/lib/visitor-guides/review-request.ts",
"text": "// Exact guide request compiler. No inference, DB, scheduler or publication side effects.\n\nimport assert from 'node:assert/strict';\n\nimport{createHash}from'node:crypto';\n\nimport{visibleBlocks}from'./visible-coverage.mjs';\n\nimport{guideResponseSchema}from'./response-schema';\n\nconst sha=(s:string)=>createHash('sha256').update(s).digest('hex');\n\nconst previousClarification=`\\nUse the exact JSON key \"confidence\" for your number, never \"numeric\". visible_coverage MUST be an array of objects. Use every supplied block ID and its exact digest, including titles, headings and checklist items. Approval requires a nonempty list of assigned source IDs for EVERY block. Generic editorial wording is not an exception. Do not invent, auto-fill or copy author source hints as proof. Read all assigned original sections and independently determine actual support. If source support is absent or a claim is materially unsupported, return a coherent rejection with the exact block digest and a relevant contiguous original source quote explaining the conflict or limitation. Do not create an irrelevant citation merely to satisfy formatting. Do not claim approval when you cannot satisfy the existing source-bound contract. Author source hints identify where to look only; they are not reviewer findings or verified support.`;\n\nexport const clarification=previousClarification+`\\nThe Swedish guide may explain or paraphrase the assigned English or Swedish originals; its wording need not be verbatim source text. Judge whether its factual claims and limits are supported, not whether explanatory prose is a literal transcription. Only source_quote in a rejection finding must be an exact contiguous original quotation. Never approve unsupported generalizations or invent citations merely because paraphrasing is allowed.`;\nexport type JobInput={draft_text:string;source_book_text:string;draft_sha256:string;source_book_sha256:string};\n\nfunction manifest(draft:any){\n\n const texts=new Map<string,string>([['title',draft.title],['dek',draft.dek]]);\n\n for(const s of draft.sections){texts.set(`section:${s.id}:heading`,s.heading);s.paragraphs.forEach((v:string,i:number)=>texts.set(`section:${s.id}:paragraph:${i}`,v));}\n\n draft.checklist.forEach((v:string,i:number)=>texts.set(`checklist:${i}`,v));\n\n return visibleBlocks(draft).map((b:{id:string;text_sha256:string})=>{const text=texts.get(b.id);assert.equal(sha(text!),b.text_sha256);const section=draft.sections.find((s:any)=>b.id.startsWith(`section:${s.id}:`));return{...b,text,author_source_hints:section?.source_refs??[],hints_are_evidence:false};});\n\n}\n\nexport function buildGuideRequest(job:JobInput,instruction:string){\n\n assert.equal(sha(job.draft_text),job.draft_sha256);assert.equal(sha(job.source_book_text),job.source_book_sha256);\n\n const draft=JSON.parse(job.draft_text),book=JSON.parse(job.source_book_text),blocks=visibleBlocks(draft),reviewer_blocks=manifest(draft),sourceIds:string[]=draft.sources.map((s:any)=>s.id);\n\n assert.deepEqual(sourceIds,[...new Set(sourceIds)]);assert(sourceIds.every((id:string)=>book.sources.some((s:any)=>s.id===id)));\n\n const {outputSchema}=guideResponseSchema(blocks,sourceIds);\n\n return{instruction:instruction+clarification,whole_draft:draft,whole_source_book:book,visible_blocks:blocks,draft_sha256:job.draft_sha256,source_book_sha256:job.source_book_sha256,reviewer_blocks,request_transport:{contract:'guide-request-schema-binding-v1',output_schema:outputSchema,output_schema_sha256:sha(JSON.stringify(outputSchema))}};\n\n}\n\nexport function validateGuideRequest(input:any,job:JobInput){\n\n assert.equal(input.draft_sha256,job.draft_sha256);assert.equal(input.source_book_sha256,job.source_book_sha256);\n\n assert.deepEqual(input.whole_draft,JSON.parse(job.draft_text));assert.deepEqual(input.whole_source_book,JSON.parse(job.source_book_text));assert.deepEqual(input.visible_blocks,visibleBlocks(JSON.parse(job.draft_text)));\n\n // Completed historical requests retain the exact original JSON-object transport.\n\n if(input.request_transport===undefined){assert.equal(input.reviewer_blocks,undefined);return undefined;}\n\n assert.equal(input.request_transport.contract,'guide-request-schema-binding-v1');\n\n assert([previousClarification,clarification].some(suffix=>input.instruction.endsWith(suffix)));assert.deepEqual(input.reviewer_blocks,manifest(input.whole_draft));\n\n const {outputSchema}=guideResponseSchema(input.visible_blocks,input.whole_draft.sources.map((s:any)=>s.id));assert.deepEqual(input.request_transport.output_schema,outputSchema);assert.equal(input.request_transport.output_schema_sha256,sha(JSON.stringify(outputSchema)));\n\n return outputSchema;\n\n}\n\nexport function recordedGuideInput(input:any){return{draft:input.whole_draft,whole_source_book:input.whole_source_book,visible_blocks:input.visible_blocks,draft_sha256:input.draft_sha256,source_book_sha256:input.source_book_sha256,...(input.request_transport?{reviewer_blocks:input.reviewer_blocks}:{})};}\n\n",
"sha256": "236d283318e21c855a6737b9f7f9640245da35fb194e554afd63491ccc85c60f",
"bytes": 4964
},
{
"path": "src/lib/visitor-guides/async-product-source-guard.ts",
"text": "// Staged read-only source guard for the two product-declaration guide drafts.\nimport {createHash} from 'node:crypto';\nimport type {Database} from '../database';\ntype Input = {draft_text:string;source_book_text:string;draft_sha256:string;source_book_sha256:string};\ntype Source = {id:string;record_id:string;version_id:string;source_url:string;captured_sections_sha256:string;original_sections?:unknown[]};\nexport const visitorGuideSourceContract='visitor-content-typed-originals-v1-20261018';\ntype TypedSource=Source&{source_type?:'product_declaration'|'authority'|'chemical_identity_collection';raw_sha256?:string;members?:{id:string;version_id:string;name:string;definition:string}[]};\nconst hash=(s:string)=>createHash('sha256').update(s).digest('hex');\nconst valid=(s:Source)=>s&&['id','record_id','version_id','source_url','captured_sections_sha256'].every(k=>typeof s[k as keyof Source]==='string'&&String(s[k as keyof Source]).trim());\n\n// Caller keeps the transaction open across this check and its guarded mutation.\n// SELECTs alone do not establish external formulation freshness or hosted parity.\nexport async function asyncProductGuideSourcesMatch(db:Database,job:Input):Promise<boolean>{\n try{\n if(!['sqlite','postgres'].includes(db.dialect??'')||hash(job.draft_text)!==job.draft_sha256||hash(job.source_book_text)!==job.source_book_sha256)return false;\n const draft=JSON.parse(job.draft_text) as {source_book_sha256?:string;sources:TypedSource[]};\n const book=JSON.parse(job.source_book_text) as {source_contract?:string;sources:TypedSource[]};\n if(draft.source_book_sha256!==job.source_book_sha256||!Array.isArray(draft.sources)||!draft.sources.length||!Array.isArray(book.sources)||draft.sources.length!==book.sources.length)return false;\n if(!draft.sources.every(valid)||!book.sources.every(valid)||new Set(draft.sources.map(s=>s.id)).size!==draft.sources.length||new Set(book.sources.map(s=>s.id)).size!==book.sources.length)return false;\n for(const source of draft.sources){\n const original=book.sources.find(s=>s.id===source.id);\n if(!original||['record_id','version_id','source_url','captured_sections_sha256'].some(k=>original[k as keyof Source]!==source[k as keyof Source]))return false;\n if(source.source_type!==original.source_type)return false;\n if(!Array.isArray(original.original_sections)||!original.original_sections.length||hash(JSON.stringify(original.original_sections))!==source.captured_sections_sha256)return false;\n if(source.source_type==='authority'){\n if(book.source_contract!==visitorGuideSourceContract||source.raw_sha256!==original.raw_sha256)return false;\n const rows=await db.query<{source_id:string;raw_text:string;raw_hash:string;payload_json:string}>(`SELECT v.source_id,v.raw_text,v.raw_hash,v.payload_json FROM ingredient_profile_source_current c JOIN ingredient_profile_source_versions v ON v.id=c.version_id WHERE c.source_id=? AND c.version_id=?`,[source.record_id,source.version_id]);\n if(rows.length!==1||rows[0].source_id!==source.record_id||hash(rows[0].raw_text)!==rows[0].raw_hash||rows[0].raw_hash!==source.raw_sha256||JSON.parse(rows[0].payload_json).url!==source.source_url)return false;\n if(JSON.stringify(original.original_sections)!==JSON.stringify([{kind:'authority',text:rows[0].raw_text}]))return false;\n continue;\n }\n if(source.source_type==='chemical_identity_collection'){\n const members=source.members;\n if(book.source_contract!==visitorGuideSourceContract||!Array.isArray(members)||!members.length||JSON.stringify(members)!==JSON.stringify(original.members)||new Set(members.map(m=>m.id)).size!==members.length||hash(JSON.stringify(members))!==source.version_id)return false;\n for(const member of members){\n const rows=await db.query<{id:string;version_id:string;name:string;definition:string}>(`SELECT s.id,s.current_version_id AS version_id,s.name,v.definition FROM substances s JOIN substance_versions v ON v.id=s.current_version_id AND v.substance_id=s.id WHERE s.id=? AND s.obsolete=0`,[member.id]);\n if(rows.length!==1||JSON.stringify(rows[0])!==JSON.stringify(member))return false;\n }\n if(JSON.stringify(original.original_sections)!==JSON.stringify(members.map(m=>({kind:'definition',text:JSON.stringify(m)}))))return false;\n continue;\n }\n if(source.source_type!==undefined&&source.source_type!=='product_declaration')return false;\n const records=await db.query<{current_version_id:string}>('SELECT current_version_id FROM retailer_product_records WHERE id=?',[source.record_id]);\n if(records.length!==1||records[0].current_version_id!==source.version_id)return false;\n const versions=await db.query<{record_id:string;payload_json:string}>('SELECT record_id,payload_json FROM retailer_product_versions WHERE id=?',[source.version_id]);\n if(versions.length!==1||versions[0].record_id!==source.record_id||JSON.parse(versions[0].payload_json).source_url!==source.source_url)return false;\n const links=await db.query<{job_id:string}>('SELECT job_id FROM retailer_recipe_links WHERE version_id=?',[source.version_id]);\n if(links.length!==1)return false;\n const jobs=await db.query<{sections_json:string}>('SELECT sections_json FROM retailer_recipe_jobs WHERE id=?',[links[0].job_id]);\n if(jobs.length!==1||jobs[0].sections_json!==JSON.stringify(original.original_sections))return false;\n }\n return true;\n }catch{return false;}\n}\n",
"sha256": "40e3c9d5125d8507078502b96ec63f3b0d7b28d4e16bd8de587fd3b2a429b4c1",
"bytes": 5388
},
{
"path": "src/components/visitor-content.tsx",
"text": "import Link from'./localized-link';\nimport{Breadcrumb,LocalizedDate}from'./ui';\nimport type{verifyVisitorPublication}from'@/lib/visitor-publications';\ntype Publication=ReturnType<typeof verifyVisitorPublication>;\nexport function VisitorContent({entry,products=[]}:{entry:Publication;products?:{id:string;record_id:string;name:string}[]}){\n const{draft,book,review}=entry;\n const refs=(blockId:string)=>review.visible_coverage.find((c:any)=>c.block_id===blockId)?.source_ids??[];\n const citations=(blockId:string)=><span className=\"fine-print\">{refs(blockId).map((id:string)=><a key={id} href={'#kalla-'+id}> [{id}]</a>)}</span>;\n return <><Breadcrumb items={[{label:'Läs om ingredienser',href:'/las'},{label:draft.title}]}/><article className=\"panel prose\"><div className=\"eyebrow\">{draft.content_kind==='area'?'ÄMNESOMRÅDE':'GUIDE'}</div><h1>{draft.title}</h1><p className=\"lead\">{draft.dek}{citations('dek')}</p><p className=\"fine-print\">Separat granskad <LocalizedDate date={review.finished_at}/>. Källornas egna datum framgår av underlagen.</p><nav aria-label=\"På denna sida\"><ul>{draft.sections.map((s:any)=><li key={s.id}><a href={'#'+s.id}>{s.heading}</a></li>)}</ul></nav>{draft.sections.map((s:any)=><section className=\"section-space\" id={s.id} key={s.id}><h2>{s.heading}</h2>{s.paragraphs.map((text:string,i:number)=><p key={i}>{text}{citations(`section:${s.id}:paragraph:${i}`)}</p>)}</section>)}<section className=\"section-space\"><h2>Att ta med</h2><ul>{draft.checklist.map((text:string,i:number)=><li key={i}>{text}{citations(`checklist:${i}`)}</li>)}</ul></section>{draft.identity_ids?.length>0&&<section className=\"section-space\"><h2>Exakta ämnesposter och forskningsvägar</h2><ul>{draft.identity_ids.map((id:string)=><li key={id}><Link href={'/amnen/'+id}>{id}</Link> · <Link href={'/forskning?substance='+id}>Forskningsregistret för ämnet</Link></li>)}</ul></section>}{products.some(p=>draft.products?.includes(p.id))&&<section className=\"section-space\"><h2>Läs verkliga produktdeklarationer</h2><ul>{products.filter(p=>draft.products?.includes(p.id)).map(p=><li key={p.record_id}><Link href={'/produkter/retailer-'+p.record_id}>{p.name}</Link></li>)}</ul></section>}<section className=\"section-space\"><h2>Källor och hela underlag</h2>{book.sources.map((s:any)=><details id={'kalla-'+s.id} key={s.id} className=\"section-space\"><summary><strong>{s.id}</strong> · {s.publisher??'Produktdeklaration'}</summary><p><a href={s.source_url} target=\"_blank\" rel=\"noreferrer\">Öppna källan</a></p>{s.capture_scope&&<p className=\"fine-print\">{s.capture_scope}</p>}{(!s.source_type||s.source_type==='product_declaration')&&<p><Link href={'/produkter/retailer-'+s.record_id}>Läs produktdeklarationen på ActiQs</Link></p>}{s.original_sections.map((o:any,i:number)=><pre style={{whiteSpace:'pre-wrap',overflowWrap:'anywhere',font:'inherit'}} key={i}>{o.text}</pre>)}</details>)}</section></article></>;\n}\n",
"sha256": "98a65a178e1960b540232848337774566316d788f36a528381216e3785e27904",
"bytes": 2924
},
{
"path": "src/components/news-photo.tsx",
"text": "import data from '@/data/news-photos.json';\nimport {assignedNewsPhoto} from '@/lib/news-photo-assignment';\nimport type {Article} from '@/lib/types';\nexport function NewsPhoto({item,eager=false}:{item:Article;eager?:boolean}){\n const photo=item.editorial_photo??assignedNewsPhoto(data,item.id);\n const url=new URL(photo.url);url.searchParams.set('w',eager?'1400':'600');url.searchParams.set('q','85');url.searchParams.set('auto','format');\n return <figure className=\"editorial-photo\"><img src={url.toString()} width={eager?1400:600} height={eager?800:400} alt=\"\" loading={eager?'eager':'lazy'} fetchPriority={eager?'high':'auto'} decoding=\"async\"/><figcaption>Illustrationsbild · <a href={photo.link} target=\"_blank\" rel=\"nofollow noopener noreferrer\">{photo.credit}</a> / <a href=\"https://unsplash.com/?utm_source=actiqs&utm_medium=referral\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Unsplash</a></figcaption></figure>;\n}\n",
"sha256": "101b511a21ddb14752f3939b56d042588c80ed4a2710ed86e2f49a1da7143bc1",
"bytes": 932
},
{
"path": "src/app/[lang]/nyheter/[slug]/page.tsx",
"text": "import { T } from '@/components/translation';\nimport { notFound } from 'next/navigation';\nimport { articles,sources } from '@/lib/catalogue';\nimport { Breadcrumb,LocalizedDate } from '@/components/ui';\nimport {NewsPhoto} from '@/components/news-photo';\nimport {ArticleActions} from '@/components/article-actions';\nimport Link from '@/components/localized-link';\nimport {cache} from 'react';\nimport {database} from '@/lib/database';\nimport {newsRelatedIngredients} from '@/lib/news-related-ingredients';\nimport {NewsRelatedIngredients} from '@/components/news-related-ingredients';\nimport {canonicalUrl,jsonLd} from '@/lib/seo';\nimport {articleStructuredData} from '@/lib/structured-data';\nconst preparedArticles=cache(()=>articles(undefined,{longform:true}));\nexport async function generateMetadata({params}:{params:Promise<{slug:string}>}){const {slug}=await params;const item=(await preparedArticles()).find(a=>a.slug===slug);return item?{title:item.title,description:item.dek,openGraph:{type:'article' as const,siteName:'ActiQs',url:canonicalUrl('/nyheter/'+item.slug),locale:'sv_SE',title:item.title,description:item.dek,...item.published_at?{publishedTime:item.published_at}: {}}}:{robots:{index:false,follow:true}};}\nexport default async function Article({params}:{params:Promise<{slug:string;lang:string}>}){\n const {slug,lang}=await params;\n const [items,sourceRows]=await Promise.all([preparedArticles(),sources()]);\n const item=items.find(i=>i.slug===slug);if(!item)notFound();\n const relatedIngredients=await newsRelatedIngredients(await database(),item);\n const source=sourceRows.find(s=>s.id===item.source_id);\n const body=JSON.parse(item.body_json) as {heading:string;text:string}[];\n return <>{lang==='sv'&&<script type=\"application/ld+json\" dangerouslySetInnerHTML={{__html:jsonLd(articleStructuredData(item))}}/>}<Breadcrumb items={[{label:'Nyheter',href:'/nyheter'},{label:item.title}]}/>\n <article className=\"article-body\">\n <div className=\"eyebrow\"><T text={item.tier==='top'?'TOPPNYHET':item.tier==='note'?'NOTIS':'ARTIKEL'}/> · {item.published_at&&<LocalizedDate date={item.published_at}/>}</div>\n <h1><T text={item.title}/></h1><p className=\"lead\"><T text={item.dek}/></p>\n <ArticleActions slug={item.slug} title={item.title}/>\n <NewsPhoto item={item} eager/>\n {body.map((section,i)=><section key={i}><h2><T text={section.heading}/></h2>{section.text.split(/\\n\\s*\\n/).filter(Boolean).map((paragraph,index)=><p key={index}><T text={paragraph}/></p>)}</section>)}\n {source&&<section className=\"panel\"><h2>Källunderlag</h2><p>{source.name}{source.publisher&&source.publisher.trim().toLowerCase()!==source.name.trim().toLowerCase()&&<> · {source.publisher}</>}</p>{item.event_date&&<p>Källans publiceringsdatum: <LocalizedDate date={item.event_date}/></p>}{item.primary_source&&<p>Kompletterande förstahandskälla: {item.primary_source.publisher} · {item.primary_source.date_label&&<>{item.primary_source.date_label}: </>}<LocalizedDate date={item.primary_source.date}/></p>}{item.primary_source?.attribution&&<p>{item.primary_source.attribution.authors}. {item.primary_source.attribution.title}. DOI: {item.primary_source.attribution.doi}. Bearbetad nyhetsredogörelse. <a href={item.primary_source.attribution.license_url}>Licens: CC BY 4.0</a>.</p>}{item.research_sources?.map((reference:{title:string;url:string;date?:string})=><p key={reference.url}><a href={reference.url} target=\"_blank\" rel=\"noreferrer\">{reference.title} ↗</a>{reference.date&&<> · Registeruppdatering: <LocalizedDate date={reference.date}/></>}</p>)}</section>}\n {relatedIngredients&&<NewsRelatedIngredients data={relatedIngredients}/>}\n <section className=\"section-space\"><h2>Läs vidare</h2>{items.filter(a=>a.id!==item.id).slice(0,3).map(a=><p key={a.id}><Link href={'/nyheter/'+a.slug}>{a.title} →</Link></p>)}</section>\n </article>\n </>;\n}\n",
"sha256": "dfbfb76f1b99150f863cfe0a98f4b35476799b99d2d78cbdeae3f83dc0281204",
"bytes": 3869
}
]
}
}
ACTIQS-OWNER · ActiQs
Direkta mänskliga besked om ActiQs bolag, kontakt och incidentansvar. Ingen e-postleverans, svarstid eller rättslig behandlingspolicy verifierad. Hela uppgiften återges här; den har ingen publik originaladress.
{
"contract": "visitor-content-first-party-originals-v1-20261019",
"publisher": "ActiQs",
"origin_kind": "owner_statement",
"claims_scope": "publisher_process_and_responsibility_only",
"recorded_at": "2026-10-19T07:43:09.003572+00:00",
"provenance": {
"statements": [
{
"question": "Vilken person eller juridisk person är ActiQs huvudman och personuppgiftsansvarig?",
"answer": "Nutri Nordic AB"
},
{
"question": "Vilken e-postadress ska användas för kontakt/rättelser och vem är incidentansvarig?",
"answer": "hello@actiqs.com\nNutri Nordic AB"
}
],
"facts": {
"principal": "Nutri Nordic AB",
"data_controller": "Nutri Nordic AB",
"contact_email": "hello@actiqs.com",
"incident_responsible": "Nutri Nordic AB"
}
}
}
ACTIQS-OWNER-CONTACT-STATUS · ActiQs
Två hela direkta mänskliga fråge/svarspar: tidigare rollbesked samt senaste avtals-/brevlådebesked. Senaste svarets stavning bevarad. Brevlådan är enligt ägaren inte upprättad. Ingen leverans, vidarebefordran, gallringsfrist eller avtalsgranskning verifierad. Tidigare fullständigt kontakt-/incidentoriginal behålls separat i hela källpaketet.
{
"contract": "visitor-content-first-party-originals-v1-20261019",
"publisher": "ActiQs",
"origin_kind": "owner_statement",
"claims_scope": "publisher_process_and_responsibility_only",
"recorded_at": "2026-10-19T09:27:17.744Z",
"provenance": {
"statements": [
{
"question": "Vilken person eller juridisk person är ActiQs huvudman och personuppgiftsansvarig, vilken fungerande e-postadress ska ta emot kontakt/rättelser och vem ansvarar för incidenter? Samma person får ha flera roller.",
"answer": "Nutri Nordic AB"
},
{
"question": "För integritetssidan behöver jag bekräfta två förhållanden som inte framgår av driftinställningarna: Är Nutri Nordic AB även avtalspart eller omfattad kund för ActiQs Vercel/Neon och Migadu? Är hello@actiqs.com en egen brevlåda hos Migadu eller vidarebefordras mejlen till en annan tjänst, och finns någon fastställd regel för när kontaktmejl raderas? Skriv gärna ”ingen fastställd regel” om en sådan saknas.",
"answer": "Ja, avtalspart. Ja, hello@actiqs.com är en genen snart. Har inte lagt upp det än"
}
],
"facts": {
"principal": "Nutri Nordic AB",
"data_controller": "Nutri Nordic AB",
"incident_responsible": "Nutri Nordic AB",
"contact_email": "hello@actiqs.com",
"contracting_statement": "Ja, avtalspart.",
"mailbox_creation_statement": "Har inte lagt upp det än"
}
}
}