Nová historie

AI agenti nejsou připraveni na výrobu - a kontrola přístupu může být důvodem

podle Permit.io12m2025/04/16
Read on Terminal Reader

Příliš dlouho; Číst

Agentury AI čelí kritickým bezpečnostním výzvám v důsledku dynamického přístupu k datům a nových vektorů útoku. Tento článek představuje rámec čtyř obvodů, který zajišťuje pracovní postupy AI prostřednictvím rychlého filtrování, ochrany dat RAG, kontroly externího přístupu a ověřování výstupů – s využitím kontroly přístupu s jemným zrnem (ABAC & ReBAC) ke zvýšení bezpečnosti AI.
featured image - AI agenti nejsou připraveni na výrobu - a kontrola přístupu může být důvodem
Permit.io HackerNoon profile picture
0-item

-Daniel Bass

-Daniel Bassová


Zlepšení výkonu aplikací prostřednictvím používání agentů umělé inteligence se stává velmi běžnou praxí - ať už v důsledku průmyslového hype nebo skutečných užitečných případů použití.


These AI agents, however, often require access to highly sensitive data, introducing significant security risks. Without standardized access control solutions, development teams often build security measures from scratch—leading to cases where AI assistants expose sensitive patient information and several AI agents being compromised through sophisticated prompt injection attacks.

AI assistants expose sensitive patient informationsophisticated prompt injection attacks


Ochrana agentů umělé inteligence v tomto kontextu se stává stejně důležitou jako schopnosti samotných agentů umělé inteligence - ne-li více.

To address this problem, we at Permit.io have been working for a while on a structured security approach I wish to introduce to you today:

Permit.io

The Four-Perimeter Framework.

The Four-Perimeter FrameworkThe Four-Perimeter Framework


This method provides a comprehensive strategy for protecting AI agents by implementing fine-grained access control, ensuring compliance, and mitigating potential attack vectors. Before I go into the solution, let’s talk more about the problem space.

fine-grained access control

Problém: bezpečnostní rizika AI v citlivých doménách

Traditional application security measures and access control mechanisms fall short when it comes to handling AI agents. While conventional access control systems like role-based access control (RBAC) excel at managing static permissions, they struggle with the dynamic nature of AI responses. Unlike traditional applications where inputs map to predictable outputs and access patterns are well-defined, AI generates unique responses for each query. This means the access control and input validation techniques we’re used to can’t anticipate all possible outputs.

role-based access control (RBAC)


The way AI systems access data also doesn’t fit security standards. To provide accurate and helpful responses, AI agents need broad access to various data sources and knowledge bases. Classic RBAC proves too rigid for this need - you can’t simply assign static permissions when the data requirements change based on context. This calls for a more sophisticated, attribute-based approach that can make dynamic access decisions.

attribute-based


Dalším problémem jsou nové vektory útoku, které systémy AI zavádějí.Konvenční bezpečnostní opatření nebyla navržena tak, aby řešila útoky rychlého vstřikování, pokusy o extrakci modelů nebo útoky na otravu dat. Tyto cílové zranitelnosti jsou jedinečné pro systémy AI, které vyžadují zcela nové metody ochrany.


Řešení přichází ve formě komplexního bezpečnostního rámce postaveného kolem čtyř základních obvodů -

Rozhodnutí: Čtyřoběžní rámec

Protože se aplikace AI liší od standardního softwaru tím, jak zpracovávají vstupy, získávají data, provádějí akce a vytvářejí výstupy, zavádějí také jedinečná bezpečnostní rizika.


The Four-Perimeter Framework is designed to enforce identity-aware, fine-grained authorization throughout the AI lifecycle. It introduces security boundaries that govern what data AI models can access, what operations they can perform, and how their responses are validated.

Čtyři perimetrální rámcefine-grained authorization throughout the AI lifecycle


Rámec se skládá ze čtyř částí:


  1. Prompt Filtering – Zajištění, že pouze validované, bezpečné vstupy dosáhnou modelů AI.
  2. RAG Data Protection – Ovládání přístupu AI k externím zdrojům znalostí.
  3. Secure External Access – Definování oprávnění AI agentů při interakci s externími nástroji.
  4. Response Enforcement – Aplikace kontrol shody a filtrování výstupů generovaných AI.
  • Rychlé filtrování – zajištění, že pouze validované, bezpečné vstupy dosáhnou modelů AI.
  • Rychlé filtrování
  • RAG Data Protection – Kontrola přístupu umělé inteligence k externím zdrojům znalostí.
  • RAG Ochrana osobních údajů
  • Secure External Access – Definování oprávnění AI agentů při interakci s externími nástroji.
  • Zabezpečení vnějšího přístupu
  • Response Enforcement – Aplikace kontrol shody a filtrování výstupů generovaných AI.
  • Reakční řízení


    Aplikací principů fine-grained access control (FGA) v těchto obvodech zůstávají agenti AI bezpeční, auditovatelní a kompatibilní – aniž by se obětovala jejich flexibilita a funkčnost.

    Kontrola přístupu s jemným zrnem (FGA)bezpečné, auditovatelné a kompatibilní

    Kde se FGA nachází?

    Jak již bylo zmíněno dříve, tradiční metody kontroly přístupu, jako je RBAC, se nedokáží vypořádat s dynamickým, kontextově závislým chováním umělé inteligence.To je místo, kde vstupuje do hry autorizace s jemným zrnem (FGA), konkrétně prostřednictvím kontroly přístupu založené na atributu (ABAC) a kontroly přístupu založené na vztahu (ReBAC):


    • ABAC pro prompt filtrování Modely AI zpracovávají nestrukturované vstupy, čímž je obtížné aplikovat tradiční bezpečnostní pravidla.Modely AI zpracovávají nestrukturované vstupy, čímž je obtížné aplikovat tradiční bezpečnostní pravidla. ABAC to řeší tím, že extrahuje strukturované atributy z AI poptávek a používá je při rozhodování o přístupu založeném na zásadách.ABAC pro promptní filtraci


      • ReBAC pro ochranu dat RAG Retrieval-augmented generation (RAG) umožňuje modelům umělé inteligence čerpat informace z vektorových databází.ReBAC poskytuje přirozený způsob, jak v tomto nastavení prosazovat bezpečnost definováním vztahů mezi uživateli, zdroji dat a agenty umělé inteligence. Namísto přidělování statických oprávnění, ReBAC dynamicky uděluje nebo odmítá přístup na základě toho, jak se datové objekty vztahují k sobě navzájem – umožňující oprávnění pro vyhledávání s vědomím kontextu.
    • ReBAC pro ochranu dat RAG Retrieval-augmented generation (RAG) umožňuje modelům umělé inteligence čerpat informace z vektorových databází.ReBAC poskytuje přirozený způsob, jak v tomto nastavení prosazovat bezpečnost definováním vztahů mezi uživateli, zdroji dat a agenty umělé inteligence. Namísto přidělování statických oprávnění, ReBAC dynamicky uděluje nebo odmítá přístup na základě toho, jak se datové objekty vztahují k sobě navzájem – umožňující oprávnění pro vyhledávání s vědomím kontextu.
    • ReBAC pro ochranu údajů RAG


      Spojením ABAC a ReBAC získávají aplikace AI flexibilní mechanismy řízení přístupu založené na zásadách, které se přizpůsobují různým pracovním postupům AI bez nutnosti ručního zásahu.

      Jak vypadá implementace krok za krokem?

      Let's walk through a practical implementation to see the Four-Perimeter Framework in action. This example secures an AI agent by validating prompts, enforcing data protection, restricting external access, and moderating responses—leveraging Permit.io AI Access Control integrations at each step.

      Four-Perimeter Framework v akcivalidace upozornění, prosazování ochrany údajů, omezení externího přístupu a moderování odpovědíPermit.io AI Access ControlPermit.io

      1 Implementovat prompt filtrování

      1 Implement Prompt filtrování

      První bezpečnostní obvod se zaměřuje na validování a sanitizaci vstupů umělé inteligence předtím, než dosáhnou modelu.Můžeme prosazovat strukturované zpracování vstupů a prosazovat přístupové politiky na výzvy předtím, než dosáhnou modelu umělé inteligence:


      • Oprávňovací kontroly jsou začleněny do rychlého ověřovacího potrubí, které brání neoprávněným údajům ovlivňovat výstupy umělé inteligence.
      • Role, atributy a kontrola přístupu založená na vztahu jsou vynucovány, což zajišťuje, že pouze schválené parametry přecházejí do umělé inteligence.
      • Jakékoli porušení zásad jsou zaznamenáváno a blokováno v reálném čase, přičemž je zachována auditovatelná sled rozhodnutí o přístupu.
      Kontrola autorizace je začleněna do rychlého ověřovacího potrubí, což zabraňuje neoprávněným datům ovlivňovat výstupy AI.
    • Role, atributy a kontrola přístupu založená na vztahu jsou vynucovány, což zajišťuje, že pouze schválené parametry přecházejí na AI.
    • Jakékoli porušení zásad jsou zaznamenáváno a blokováno v reálném čase, přičemž je zachována auditovatelná sled rozhodnutí o přístupu.

    • Zde jsou tři metody filtrování poptávek - od nejjednodušších po nejpokročilejší:


      1. Validace tokenů - Efektivní metoda pro jednoduché kontroly, jako je délka příkazu nebo obecné povolení běžících vstupů v systému. Funkce kontroly oprávnění v této metodě zkoumají strukturované atributy textových příkazů.
      2. Pattern Matching - v této metodě kontrola oprávnění zkoumá vzory v textu příkazu. Kontrola, například, zda vzor odpovídá dotazu SQL nebo kódu příkladu.
      3. AI klasifikace - nejpokročilejší metoda v tomto seznamu, klasifikace AI používá AI k analýze příkazu pomocí dedikovaného systémového příkazu, klasifikuje do něj strukturovaný vstup, který lze přes
      4. Validace tokenů - Efektivní metoda pro jednoduché kontroly, jako je délka poptávky nebo obecné povolení běžících vstupů v systému.Válení tokenů
      5. Pattern Matching - v této metodě kontrola oprávnění zkoumá vzory v poptávkovém textu.Paternová shoda
      6. AI klasifikace - nejpokročilejší metoda v tomto seznamu, klasifikace AI používá AI k analýze poptávky pomocí specializované systémové poptávky, klasifikace do strukturovaného vstupu, který může být přesně analyzován v kontrole oprávnění.
      7. I klasifikace



        Prompt filtrování s PydanticAI

        Rychlé filtrování s PydanticAIChcete-li nejlépe demonstrovat implementaci efektivního filtrování příkazů, zde je příklad použití nástrojů PydanticAI pro filtrování vstupů uživatelů do agentů AI. PydanticAI je agentový rámec, který využívá známou knihovnu Python Pydantic a její statické možnosti psaní a přeměňuje jej na strukturovaný rámec AI, který se zabývá nestrukturovanými daty.



        The following GitHub repository contains a full implementation of the framework for PydanticAI: github.com/permitio/permit-pydanticai

        github.com/permitio/permit-pydanticai


         @financial_agent.tool async def validate_financial_query( ctx: RunContext[PermitDeps], dotaz: FinancialQuery, ) -> bool: ""Key checks: - Uživatel se výslovně rozhodl pro AI finanční poradenství, Falešný jinak "" zkuste: #Classify je správně zaznamenáno a ověřeno - Klasifikuje je-li výzva žádá o poradenství Args: ctx: Kontext obsahující Permit klient a uživatel ID dotaz: Finanční dotaz pro ověření Returns: bool: True pokud uživatel souhlasil s AI poradenství, Falešný jinak "" zkuste: #Classify je-li výz
        @financial_agent.tool
        async def validate_financial_query(
            ctx: RunContext[PermitDeps],
            query: FinancialQuery,
        ) -> bool:
            """Key checks:
            - User has explicitly opted in to AI financial advice
            - Consent is properly recorded and verified
            - Classifies if the prompt is requesting advice
        
            Args:
                ctx: Context containing Permit client and user ID
                query: The financial query to validate
        
            Returns:
                bool: True if user has consented to AI advice, False otherwise
            """
            try:
                # Classify if the prompt is requesting advice
                is_seeking_advice = classify_prompt_for_advice(query.question)
        
                permitted = await ctx.deps.permit.check(
                    # The user object with their attributes
                    {
                        "key": ctx.deps.user_id,
                    },
                    # The action being performed
                    "receive",
                    # The resource being accessed
                    {
                        "type": "financial_advice",
                        "attributes": {"is_ai_generated": is_seeking_advice},
                    },
                )
        
                if not permitted:
                    if is_seeking_advice:
                        return "User has not opted in to receive AI-generated financial advice"
                    else:
                        return "User does not have permission to access this information"
        
                return True
        
            except PermitApiError as e:
                raise SecurityError(f"Permission check failed: {str(e)}")
        

        2. Ochrana osobních údajů –

        2 Posílit ochranu osobních údajů –

        Dále zabezpečujeme recovery-augmented generation (RAG) dotazy tím, že zajistíme, že modely AI mají přístup pouze k autorizovaným zdrojům znalostí.Zvýšená generace obnovy (RAG)autorizované zdroje znalostí


        • Fine-grained politika používá pokročilé modely filtrování dat, jako je kontrola přístupu založená na vztahu, aby umožnila pokročilé filtrování dotazů do motoru politiky.
        • Vektorové a grafové zdroje spojené s AI agenty mají metadata, která mohou pomoci motoru manipulovat s nestrukturovaným dotazem a filtrovat ho tak, aby zahrnoval pouze povolené údaje.
        • Pokaždé, když agent získá data z RAG znalostní základny, filtrová výsledky na základě souhlasu uživatele.
      8. Dokončená politika používá pokročilé modely filtrování dat, jako je kontrola přístupu založená na vztahu, která umožňuje filtrování pokročilých dotazů do nástroje politik.
      9. Vektorové a grafové zdroje připojené k agentům AI mají metadata, která mohou pomoci motoru manipulovat s nestrukturovanou dotazem a filtrovat ji tak, aby zahrnovala pouze povolená data.
      10. Pokaždé, když agent získá data z databáze znalostí RAG, filtruje výsledky podle oprávnění uživatele.

      11. Když agentová aplikace provádí filtraci RAG, používá jednu z následujících metod:


        • FilterObjects – V této metodě aplikace grafu získá všechna relevantní data z RAG a poté ji filtrová na uživatelská oprávnění. Výhodou této funkce je, že udržuje zásadový engine bez statusu a nepozná data RAG.
        • GetUserPermissions - V této metodě agent poskytuje RAG nestrukturovaný dotaz. RAG pak volá funkci GetUserPermissions a připojuje dotaz filtru k nestrukturovanému dotazům RAG. To umožňuje, aby byl dotaz filtrován pouze na zdroje, ke kterým může uživatel přistupovat.
      12. FilterObjects – V této metodě aplikace grafu získá veškerá relevantní data z RAG a potom ji filtrová na uživatelská oprávnění.FilterObjects
      13. GetUserPermissions - V této metodě agent poskytuje RAG nestrukturovaný dotaz. RAG pak zavolá funkci GetUserPermissions a připojí dotaz filtru k nestrukturovanému dotazům RAG.GetUserPermissionsGetUserPermissions


        RAG Ochrana dat s Langchain

        RAG Ochrana dat s Langchain

        Langchain, známý AI aplikační rámec, je známý (také) svými retrieverovými komponenty, které poskytují skvělou podporu v přizpůsobených retrieverech, které lze sestavit s jakýmkoli zdrojem dat, což usnadňuje implementaci zabezpečeného RAG. Například s SelfQueryRetriever můžete obalovat obvyklý RAG s GetUserPermissions funkcí, která přidá filtrované údaje do dotazu.SelfQueryRetrieverGetUserPermissions

         # 1. Vytvořte malé vektorové ukládání v paměti = OpenAIEmbeddings() vektorstore = FAISS.from_documents(docs, embedding=embeddings) # 2. Inicializujte PermitSelfQueryRetriever retriever = PermitSelfQueryRetriever( api_key=os.getenv("PERMIT_API_KEY", ""), pdp_url=os.getenv("PERMIT_PDP_URL"), user=USER, resource_type=RESOURCE_TYPE, action=ACTION, llm=embeddings, vectorstore=vectorstore, enable_limit=False, 
        # 1. Build a small in-memory vector store embeddings = OpenAIEmbeddings() vectorstore = FAISS.from_documents(docs, embedding=embeddings) # 2. Initialize the PermitSelfQueryRetriever retriever = PermitSelfQueryRetriever( api_key=os.getenv("PERMIT_API_KEY", ""), pdp_url=os.getenv("PERMIT_PDP_URL"), user=USER, resource_type=RESOURCE_TYPE, action=ACTION, llm=embeddings, vectorstore=vectorstore, enable_limit=False, )


        The following repository contains the full implementation of the framework for Langchain: https://github.com/permitio/langchain-permit

        https://github.com/permitio/langchain-permit

        3. zabezpečení externího přístupu –

        3. zabezpečení vnějšího přístupu –

        Agenti AI často interagují s externími API, službami a nástroji pro automatizaci. Bez řádné kontroly přístupu riskují, že budou provádět neoprávněné akce.


        • Using models like MCP, which defines a server-client model where AI agents interact with external services, is a great step in enabling security for AI external access (e.g., databases, APIs, payment systems).
        • The AI action infrastructure can use a service like Permit.io to perform authorization checks at the action level, checking who’s making a request and what action they want to perform.
        • Developers are able to assign machine identities to AI agents, limiting their capabilities to pre-approved functions only.
        Použití modelů, jako je MCP, který definuje model server-klient, ve kterém agenti AI interagují s externími službami, je skvělým krokem k umožnění zabezpečení pro externí přístup AI (např. databáze, API, platební systémy).
      14. The AI action infrastructure can use a service like Permit.io to perform authorization checks at the action level, checking who’s making a request and what action they want to perform.
      15. Permit.io
      16. Vývojáři jsou schopni přiřadit identity strojů agentům umělé inteligence, omezit jejich schopnosti pouze na předem schválené funkce.

      17. Ačkoli GPT a rozhraní přirozeného jazyka nejsou nové, nechat je provádět akce jménem uživatelů je poměrně novou výzvou, se kterou se mnozí inženýři potýkají.


        1. Bezpečnost přímého přístupu - nejjednodušší úroveň. Uživatel žádá agenta AI o provedení operace, jako je volání HTTP. Agent AI ví, zda je operace povolena, s přihlédnutím k aktuálnímu kontextu a uživateli.
        2. Komunikace mezi agentem a agentem - v této další úrovni vyžadujeme kaskádový tok identit a oprávnění, které umožňují agentům provádět akce samy na základě principu nejmenšího privilegia. Na této úrovni bychom chtěli použít vztah mezi identitami - lidskými a nelidskými - k kaskádování různých úrovní oprávnění.
        3. Přihláška k přístup
        4. Bezpečnost přímého přístupu - nejjednodušší úroveň. uživatel požádá agenta AI o provedení operace, jako je volání HTTP. Bezpečnost přímého přístupu
        5. Komunikace agent-to-agent - v této další úrovni potřebujeme kaskádový tok identit a oprávnění, které umožňují agentům provádět akce samy na základě principu nejmenšího privilegia.Komunikace mezi agentem a agentem
        6. Průtok požadavků na přístup - nejvíce vzrušující úroveň externího přístupu je, když agent AI chápe potřebu požádat o přístup přímo od lidského uživatele, když chce provést operaci.Přesuny požadavků na přístup


          MCP, Human-in-the-Loop a externí přístup

          MCP, Human-in-the-Loop a externí přístup

          Model Context Protocol je nový protokol zavedený společností Anthropic, který řeší problém umožnění AI agentům provádět proaktivní akce a slouží jako největší facilitátor pro zajištění externího přístupu.


          V následujícím příkladu ukazujeme server MCP, který ví, jak spravovat toky žádostí o přístup tím, že do kruhu přivádí lidi a používá API Permit.io k žádosti o oprávnění.


          You can see the full code example for the MCP access request server here: https://github.com/permitio/permit-mcp

          https://github.com/permitio/permit-mcp


          @mcp.tool() async def request_access(username: str, resource_name: str) -> dict: "" Initiate access request call to a specific resource in the system Args: username: The username of the person requesting access resource: The resource type the user is requesting access for resource_name: The name of the restaurant to request access for """ = wait permit.elements.login_as({ "userId": slugify(username), "tenant: "default"}) print(login): url = "https://pay.permit.io/v2/facts/{PROJECT_ID}/{ENV_ID}/{ENV_ID}/access_quests@mcp.tool()
          async def request_access(username: str, resource: str, resource_name: str) -> dict:
            """
            Initiate access request call to a specific resource in the system
          
            Args:
              username: The username of the person requesting access
              resource: The resource type the user is request access for
              resource_name: The name of the restaurant to request access for
          
            """
            
            login = await permit.elements.login_as({ "userId": slugify(username), "tenant": "default"})
            print(login)
            
            url = f"https://api.permit.io/v2/facts/{PROJECT_ID}/{ENV_ID}/access_requests/{ELEMENTS_CONFIG_ID}/user/{slugify(username)}/tenant/default"
            payload = {
                "access_request_details": {
                    "tenant": "default",
                    "resource": resource,
                    "resource_instance": resource_name['id'],
                    "role": "viewer",
                },
                "reason": f"User {username} requests role 'viewer' for {resource_name}"
            }
            headers = {
                "authorization": "Bearer YOUR_API_SECRET_KEY",
                "Content-Type": "application/json",
            }
            async with httpx.AsyncClient() as client:
                await client.post(url, json=payload, headers=headers)
                return "Your request has been sent. Please check back later."
          

          4 Validovat AI odpovědi –

          4 Validovat AI odpovědi –

          Konečný obvod zavádí moderování obsahu a dodržování požadavků na odpovědi generované umělou inteligencí.To lze provést vytvořením pracovního postupu, který používá filtrování založené na zásadách před dodáním výstupů umělé inteligence:


          Do agentové aplikace lze přidat kontrolu oprávnění, která umožňuje prosazování zásad v každém kroku řetězce předtím, než uživatel skutečně obdrží odpověď.
        7. Spojené pracovní postupy pro ověřování dat a autorizaci zajišťují, že pouze ověřené a povolené údaje mohou pokračovat.
        8. Odpověď, která se vrací uživatelům, může být upravena na základě předdefinovaných omezení, což umožňuje maskování dat nebo informování uživatele o omezeních použití.
    Do aplikace agenta může být přidána kontrola oprávnění, která umožňuje prosazování zásad v každém kroku řetězce předtím, než uživatel skutečně obdrží odpověď.
  • Spojené pracovní postupy validace dat a autorizace zajišťují, že pouze validovaná a povolená data mohou pokračovat.
  • Odpověď, která se vrací uživatelům, může být upravena na základě předdefinovaných omezení, což umožňuje maskování dat nebo informování uživatele o omezeních použití.



    Odpověď filtrování pomocí Langflow

    Odpověď filtrování s Langflow

    In the following example, we use Langflow, a visual no-code AI applications editor, to create a permissions check component that’s positioned before any chat response to the user. Using LangFlow's friendly flow modeling capabilities, you can easily append another component that masks unwanted details in returned responses. This repository contains all the access control components required for secured Langflow applications.

    This repository


    Závěrečná zpráva

    Systémy umělé inteligence se rychle integrují do aplikací napříč průmyslovými odvětvími, ale jejich bezpečnostní rámce zůstávají ve srovnání s tradičním softwarem nedostatečně rozvinuté.Bez řádné kontroly přístupu s vědomím totožnosti mohou agenti umělé inteligence vystavovat citlivé údaje, provádět neoprávněné operace a generovat reakce, které nespadají do souladu s pokyny.



    Rámec čtyř obvodů nabízí strukturovaný způsob, jak zabezpečit pracovní postupy v oblasti umělé inteligence v každé fázi – od validace poptávek a ochrany dat RAG až po řízení vnějších akcí řízených umělou inteligencí a prosazování souladu s reakcemi.Využitím autorizace s jemným zrnem (FGA) s ABAC a ReBAC mohou vývojáři zajistit, aby agenti umělé inteligence zůstali funkční a bezpeční a dynamicky se přizpůsobovali bezpečnostním scénářům v reálném světě.


    Instead of building access control from scratch, Permit.io’s AI Access Control integrations with PydanticAI, LangChain, MCP, and LangFlow allow teams to embed security directly into their AI applications—without disrupting development workflows. Try it yourself here.

    Try it yourself here


    To znamená, že toto pole je stále relativně nové a osvědčené postupy pro zabezpečení agentů umělé inteligence se stále vyvíjejí.Rámec čtyř obvodů je experimentálním přístupem a přestože poskytuje silný základ, uznávám, že nasazení v reálném světě vždy vyžadují další zdokonalování a přizpůsobení.


    I’d love to hear your feedback, thoughts, and ideas on how to improve this framework to make it even better for production-ready AI systems - comment here, or hit me up in our Slack community.

    Slack community

    Trending Topics

    blockchaincryptocurrencyhackernoon-top-storyprogrammingsoftware-developmenttechnologystartuphackernoon-booksBitcoinbooks