Learn Computer Science
from the ground up.
A complete, structured curriculum covering everything from binary arithmetic to artificial intelligence — 14 modules, all self-paced, built right into this file.
14 modules · All skill levels · No internet required
Module 01

Foundations of Computing

⏱ ~45 min 🟢 Beginner 🧮 Theory

Before writing a single line of code, it pays to understand what a computer actually is — and how it came to exist. Computer Science is not merely programming; it is the study of computation itself: what can be computed, how efficiently, and with what resources.

In this module we explore the philosophical and physical roots of computing, the binary number system that underlies all digital information, and the logic gates from which every processor is built.

What is Computer Science?

Computer Science is the disciplined study of algorithms (step-by-step problem-solving procedures), data structures (ways to organize information), and the theoretical limits of what machines can compute. It bridges pure mathematics, electrical engineering, linguistics, and cognitive science.

A useful distinction: programming is a craft — the act of writing instructions for a machine. Computer Science is the underlying science that tells us which instructions are possible, efficient, or even computable at all.

🧮
Algorithms
Precise, finite procedures to solve problems step by step.
📦
Data Structures
Organized ways to store and retrieve information.
⚙️
Architecture
How physical hardware executes instructions.
🔬
Theory
Mathematical models of computation and complexity.

A Brief History

Charles Babbage (1791–1871) designed the first mechanical computer concept — the Analytical Engine. His collaborator Ada Lovelace wrote what is considered the first algorithm, making her the world's first programmer.

Alan Turing (1912–1954) formalized the concept of computation in 1936 with his Turing Machine — an abstract device that defined the limits of what any computer could ever calculate. He also cracked the Nazi Enigma cipher and invented the foundational ideas behind AI.

John von Neumann (1903–1957) designed the architecture almost all modern computers use: a CPU, memory, and input/output devices, where both programs and data live in the same memory space.

The first electronic computer, ENIAC (1945), filled a room and consumed 150 kilowatts of power. Today a smartphone holds billions of times more computing power in a chip smaller than your fingernail.

The Binary Number System

All digital computers store and process information as binary — a base-2 number system using only two symbols: 0 and 1. Why? Because transistors (the fundamental component of all chips) can be either off (0) or on (1), making binary a perfect physical representation.

A single binary digit is called a bit. Eight bits form a byte, which can represent 256 different values (2⁸ = 256).

Binary Counting
// Decimal → Binary conversion
// Each position is a power of 2 (right to left)

// Position:  8  4  2  1   (powers of 2)
// Binary:    0  0  0  0  = 0  in decimal
// Binary:    0  0  0  1  = 1  in decimal
// Binary:    0  0  1  0  = 2  in decimal
// Binary:    0  0  1  1  = 3  in decimal
// Binary:    0  1  0  1  = 5  in decimal
// Binary:    1  0  0  1  = 9  in decimal
// Binary:    1  1  1  1  = 15 in decimal

// In JavaScript:
let decimal = 42;
let binary  = decimal.toString(2);  // "101010"
let back    = parseInt("101010", 2); // 42
💡
Why Base 2?

Computers use binary because electrical signals are either present (1) or absent (0). Representing more digits would require distinguishing finer voltage levels — prone to errors and noise. Binary is robust and physically natural.

Boolean Logic

Boolean algebra, developed by George Boole in 1854, is the mathematics of true/false values. It is the direct foundation of digital circuits. Every computation ever performed by a computer is ultimately a combination of three operations: AND, OR, and NOT.

ABA AND BA OR BNOT AA XOR B
000010
010111
100101
111100

Physical logic gates implement these operations using transistors. Millions of such gates form an Arithmetic Logic Unit (ALU), which performs all the arithmetic and comparisons inside a CPU.

How a Computer Works

A modern computer follows the Von Neumann architecture: instructions and data share the same memory, and the CPU repeatedly fetches, decodes, and executes instructions in a cycle.

🧠
CPU
Executes instructions. Contains ALU, Control Unit, and registers.
💾
RAM
Fast, temporary storage. Holds the running program and active data.
💿
Storage
Slow, permanent storage. Hard drives, SSDs, flash memory.
↔️
I/O
Keyboard, display, network — the computer's interface to the world.

✅ Key Takeaways

  • Computer Science studies computation — algorithms, data, and theory — not just programming.
  • Computers represent all data as binary (base-2) numbers using bits and bytes.
  • Boolean logic (AND, OR, NOT) is the mathematical foundation of all digital circuits.
  • Modern computers use the Von Neumann architecture: CPU + shared memory for code and data.
  • Alan Turing defined the theoretical limits of computation before physical computers existed.
Module 02

Programming Fundamentals

⏱ ~60 min🟢 Beginner💻 JavaScript

Programming is the art of expressing solutions to problems in a language that a computer can execute. Before learning any specific language deeply, understanding the universal building blocks of programming will make you fluent in any language far faster.

This module teaches variables, control flow, functions, and scope using JavaScript as the demonstration language — though every concept applies in Python, Java, C, and beyond.

Variables & Data Types

A variable is a named container that holds a value in memory. Every piece of data a program works with — a number, a name, a flag — lives in a variable. Data types define what kind of value a variable holds.

JavaScript
// Primitive data types
let age       = 25;          // Number (integer)
let price     = 9.99;        // Number (float)
let name      = "Alice";     // String
let isLoggedIn = true;       // Boolean
let nothing   = null;        // Null (intentionally empty)
let notDefined;               // undefined (declared, not assigned)

// const = cannot be reassigned; let = can be reassigned
const PI = 3.14159;
PI = 3; // ❌ TypeError: Assignment to constant variable

// Type checking
typeof "hello"  // "string"
typeof 42       // "number"
typeof true    // "boolean"

Operators & Expressions

Operators combine values to produce new values. An expression is any combination of values, variables, and operators that evaluates to a single result.

JavaScript
// Arithmetic operators
10 + 3   // 13  (addition)
10 - 3   // 7   (subtraction)
10 * 3   // 30  (multiplication)
10 / 3   // 3.33 (division)
10 % 3   // 1   (modulus — remainder)
2 ** 8   // 256 (exponentiation)

// Comparison operators (return boolean)
5 === 5  // true  (strict equality)
5 !== 6  // true  (strict inequality)
5 > 3    // true
5 <= 5   // true

// Logical operators
true && false  // false (AND)
true || false  // true  (OR)
!true          // false (NOT)

Control Flow

Programs rarely execute line by line from top to bottom. Control flow statements let you make decisions and repeat actions — the foundation of all non-trivial logic.

JavaScript — Conditionals
let score = 78;
let grade;

if (score >= 90) {
  grade = "A";
} else if (score >= 80) {
  grade = "B";
} else if (score >= 70) {
  grade = "C";        // ← this branch executes
} else {
  grade = "F";
}

// Ternary operator (inline if)
let pass = score >= 60 ? "Pass" : "Fail"; // "Pass"
JavaScript — Loops
// for loop: run a set number of times
for (let i = 0; i < 5; i++) {
  console.log(i);   // prints 0 1 2 3 4
}

// while loop: run while condition is true
let count = 0;
while (count < 3) {
  console.log("Tick" + count);
  count++;
}

// for…of: iterate over an array
const fruits = ["apple", "banana", "cherry"];
for (const fruit of fruits) {
  console.log(fruit);  // apple, banana, cherry
}

Functions

A function is a reusable, named block of code that performs a specific task. Functions accept parameters (inputs) and may return a value (output). They are the primary tool for organizing code and avoiding repetition.

JavaScript — Functions
// Function declaration
function add(a, b) {
  return a + b;
}
add(3, 4); // 7

// Arrow function (concise syntax)
const multiply = (a, b) => a * b;
multiply(3, 4); // 12

// Default parameters
function greet(name = "World") {
  return `Hello, ${name}!`;
}
greet();          // "Hello, World!"
greet("Alice");   // "Hello, Alice!"

// Higher-order function (takes function as argument)
const nums = [1, 2, 3, 4, 5];
const evens  = nums.filter(n => n % 2 === 0); // [2, 4]
const doubled = nums.map(n => n * 2);         // [2,4,6,8,10]

Scope & the Call Stack

Scope determines where in your code a variable is accessible. Variables declared inside a function are local to that function. Variables declared outside any function are global. Understanding scope prevents subtle bugs where variables unexpectedly overwrite each other.

The call stack is a data structure the runtime uses to track which function is currently running. When you call a function, it is pushed onto the stack. When it returns, it is popped off. A stack overflow occurs when the stack grows too deep — usually from infinite recursion.

✅ Key Takeaways

  • Variables hold typed values; prefer const unless reassignment is needed.
  • Control flow (if/else, loops) lets programs make decisions and repeat work.
  • Functions are reusable blocks; they take inputs (parameters) and return outputs.
  • Scope controls variable visibility — local variables are isolated inside functions.
  • The call stack tracks active function calls; deep recursion can overflow it.
Module 03

Data Structures

⏱ ~75 min🟡 Intermediate💻 JavaScript

Data structures are the backbone of efficient software. Choosing the right structure can be the difference between a program that runs in milliseconds and one that takes hours. Every major algorithm assumes a particular data structure, so mastering these is essential before tackling algorithms.

Arrays

An array (or list) is the simplest and most universally used data structure. It stores elements in contiguous memory at indexed positions, enabling O(1) random access — you can jump to any element instantly by its index.

JavaScript — Arrays
const arr = [10, 20, 30, 40];
arr[0];           // 10  — O(1) access
arr.push(50);     // add to end — O(1)
arr.pop();        // remove from end — O(1)
arr.shift();      // remove from front — O(n) shifts all elements
arr.splice(1,1); // remove at index 1 — O(n)
arr.length;       // 4

// 2D array (matrix)
const matrix = [[1,2],[3,4],[5,6]];
matrix[1][0]; // 3

Linked Lists

A linked list is a chain of nodes, each holding a value and a reference (pointer) to the next node. Unlike arrays, nodes need not be adjacent in memory — making insertions and deletions at arbitrary positions O(1) — but random access is O(n) because you must traverse the chain.

JavaScript — Linked List
class Node {
  constructor(value) {
    this.value = value;
    this.next  = null;
  }
}

class LinkedList {
  constructor() { this.head = null; }

  append(val) {
    const node = new Node(val);
    if (!this.head) { this.head = node; return; }
    let cur = this.head;
    while (cur.next) cur = cur.next;
    cur.next = node;
  }
}

// head → [1] → [2] → [3] → null
const list = new LinkedList();
[1,2,3].forEach(v => list.append(v));

Stacks & Queues

A stack enforces Last In, First Out (LIFO) order — like a stack of plates; you always add and remove from the top. Used in function call stacks, undo operations, and expression evaluation.

A queue enforces First In, First Out (FIFO) order — like a checkout line. Used in task scheduling, breadth-first search, and message buffers.

JavaScript — Stack & Queue
// Stack (using array)
const stack = [];
stack.push(1);  // [1]
stack.push(2);  // [1, 2]
stack.push(3);  // [1, 2, 3]
stack.pop();   // 3 ← last in, first out
stack.pop();   // 2

// Queue (using array — shift is O(n); use deque for O(1))
const queue = [];
queue.push("A");  // enqueue
queue.push("B");
queue.push("C");
queue.shift();   // "A" ← first in, first out
queue.shift();   // "B"

Hash Tables (Maps)

A hash table maps keys to values using a hash function that converts a key into a numeric index. This enables average O(1) lookup, insertion, and deletion — making it one of the most powerful and widely used data structures in existence.

JavaScript — Hash Map
const map = new Map();
map.set("alice", 95);
map.set("bob", 87);
map.get("alice");   // 95 — O(1)
map.has("carol");   // false
map.delete("bob");

// Classic use-case: counting frequencies
const freq = (arr) => {
  const counts = {};
  for (const x of arr)
    counts[x] = (counts[x] || 0) + 1;
  return counts;
};
freq(["a","b","a","c","a"]); // {a:3, b:1, c:1}

Trees & Graphs

A tree is a hierarchical structure of nodes. Each node has a parent (except the root) and zero or more children. The most common is the Binary Search Tree (BST), where every left child < parent < right child, enabling O(log n) search.

A graph is the most general structure: a set of nodes (vertices) connected by edges. Trees are a special case of graphs. Graphs model networks, social connections, maps, and more.

JavaScript — Binary Search Tree
class BSTNode {
  constructor(val) {
    this.val = val;
    this.left = this.right = null;
  }
}

function insert(root, val) {
  if (!root) return new BSTNode(val);
  if (val < root.val) root.left  = insert(root.left,  val);
  else               root.right = insert(root.right, val);
  return root;
}

// Build a BST from [5, 3, 7, 1, 4]
//        5
//       / \
//      3   7
//     / \
//    1   4
StructureAccessSearchInsertDeleteBest For
ArrayO(1)O(n)O(n)O(n)Random access, iteration
Linked ListO(n)O(n)O(1)O(1)Frequent insertions
StackO(n)O(n)O(1)O(1)LIFO operations
Hash TableO(1) avgO(1) avgO(1) avgKey-value lookup
BSTO(log n)O(log n)O(log n)O(log n)Sorted data, range queries

✅ Key Takeaways

  • Arrays provide O(1) access by index but O(n) insertion/deletion in the middle.
  • Linked lists allow O(1) insertion/deletion at any point, but O(n) access.
  • Hash tables are the most powerful general-purpose structure for O(1) key lookup.
  • Trees model hierarchical data; BSTs keep sorted order for efficient search.
  • Choosing the right data structure is often more impactful than optimizing algorithms.
Module 04

Algorithms & Complexity

⏱ ~80 min🟡 Intermediate🔄 Core CS

An algorithm is a precise, finite sequence of instructions to solve a problem. The study of algorithms asks: does this work? (correctness), how fast is it? (time complexity), and how much memory does it need? (space complexity).

Big O Notation

Big O notation describes how an algorithm's performance scales with input size n. It measures the worst-case growth rate, discarding constants and lower-order terms. It is the universal language for comparing algorithm efficiency.

O(1) — Constant
Hash table lookup. Always the same time regardless of input size.
📊
O(log n) — Logarithmic
Binary search. Halves the problem each step.
📈
O(n) — Linear
Linear search. Must look at every element once.
📉
O(n log n)
Merge sort, heap sort. Optimal for comparison sorts.
🐌
O(n²) — Quadratic
Bubble sort, nested loops over all pairs.
💥
O(2ⁿ) — Exponential
Brute-force subsets. Becomes unusable quickly.
📐
Reading Big O

O(n²) means: if you double the input, the runtime roughly quadruples. For n = 1,000 elements, an O(n²) algorithm does ~1,000,000 operations; O(n log n) does ~10,000. At scale, this difference is enormous.

Sorting Algorithms

Sorting is one of the most studied problems in CS. Understanding how different sorts work builds intuition for trade-offs between simplicity and performance.

JavaScript — Bubble Sort O(n²)
function bubbleSort(arr) {
  const n = arr.length;
  for (let i = 0; i < n - 1; i++) {
    for (let j = 0; j < n - i - 1; j++) {
      if (arr[j] > arr[j+1]) {
        [arr[j], arr[j+1]] = [arr[j+1], arr[j]]; // swap
      }
    }
  }
  return arr;
}
// Each pass "bubbles" the largest unsorted element to the end
JavaScript — Merge Sort O(n log n)
function mergeSort(arr) {
  if (arr.length <= 1) return arr;

  const mid   = Math.floor(arr.length / 2);
  const left  = mergeSort(arr.slice(0, mid));
  const right = mergeSort(arr.slice(mid));

  return merge(left, right);
}

function merge(a, b) {
  const res = [];
  let i = 0, j = 0;
  while (i < a.length && j < b.length)
    res.push(a[i] <= b[j] ? a[i++] : b[j++]);
  return res.concat(a.slice(i), b.slice(j));
}
// Divide-and-conquer: split → sort halves → merge back

Searching Algorithms

JavaScript — Binary Search O(log n)
// REQUIRES: sorted array
function binarySearch(arr, target) {
  let lo = 0, hi = arr.length - 1;

  while (lo <= hi) {
    const mid = Math.floor((lo + hi) / 2);
    if (arr[mid] === target) return mid;    // found
    if (arr[mid] < target)  lo = mid + 1; // search right half
    else                     hi = mid - 1; // search left half
  }
  return -1; // not found
}
// On 1,000,000 elements: linear = 1M checks; binary = ~20 checks

Recursion & Dynamic Programming

Recursion is when a function calls itself on a smaller sub-problem. Every recursive solution needs a base case (the stopping condition) and a recursive case.

Dynamic programming (DP) solves problems by breaking them into overlapping sub-problems and memoizing (caching) results to avoid redundant computation. It transforms exponential algorithms into polynomial ones.

JavaScript — Fibonacci: Naive vs DP
// NAIVE — O(2ⁿ): redundantly recomputes sub-problems
function fibSlow(n) {
  if (n <= 1) return n;
  return fibSlow(n-1) + fibSlow(n-2);
}

// MEMOIZED — O(n): cache each result once
const fibFast = (n, memo = {}) => {
  if (n in memo) return memo[n];
  if (n <= 1)    return n;
  memo[n] = fibFast(n-1, memo) + fibFast(n-2, memo);
  return memo[n];
};
// fibFast(50) runs instantly; fibSlow(50) would take minutes

✅ Key Takeaways

  • Big O notation describes worst-case growth — prefer O(log n) or O(n) over O(n²).
  • Merge sort (O(n log n)) is optimal for comparison-based sorting of large datasets.
  • Binary search requires sorted data but reduces a million-item search to ~20 comparisons.
  • Recursion requires a base case; without one, it loops forever (stack overflow).
  • Dynamic programming turns exponential brute-force into polynomial time by caching sub-results.
Module 05

Object-Oriented Programming

⏱ ~60 min🟡 Intermediate🎯 Design

Object-Oriented Programming (OOP) is a programming paradigm that organizes code around objects — bundles of data (fields) and behavior (methods). It enables large, complex systems to be built and maintained by modeling real-world entities and their relationships.

Classes & Objects

A class is a blueprint that defines the structure and behavior of objects. An object (or instance) is a concrete realization of that blueprint. Think of a class as the concept of a "Car" and an object as a specific car — your red Honda with 30,000 miles on it.

JavaScript — Classes
class BankAccount {
  constructor(owner, balance = 0) {
    this.owner   = owner;
    this.balance = balance;
    this.#txLog  = [];        // private field (#)
  }

  deposit(amount) {
    this.balance += amount;
    this.#txLog.push(`+${amount}`);
  }

  withdraw(amount) {
    if (amount > this.balance) throw new Error("Insufficient funds");
    this.balance -= amount;
  }

  toString() {
    return `${this.owner}: $${this.balance}`;
  }
}

const acc = new BankAccount("Alice", 1000);
acc.deposit(500);
acc.withdraw(200);
console.log(acc.toString()); // "Alice: $1300"

The Four Pillars of OOP

🔒
Encapsulation
Hide internal state; expose only a safe public interface. Prevents unintended mutations.
🧬
Inheritance
A child class extends a parent, inheriting its fields and methods and adding new ones.
🎭
Polymorphism
One interface, many implementations. A shape can be a circle or square; both respond to area().
🌫️
Abstraction
Expose what's necessary, hide complexity. You drive a car without understanding the engine.
JavaScript — Inheritance & Polymorphism
class Shape {
  area() { throw new Error("Subclass must implement area()"); }
  toString() { return `Area: ${this.area().toFixed(2)}`; }
}

class Circle extends Shape {
  constructor(r) { super(); this.r = r; }
  area()         { return Math.PI * this.r ** 2; }
}

class Rectangle extends Shape {
  constructor(w, h) { super(); this.w=w; this.h=h; }
  area()            { return this.w * this.h; }
}

// Polymorphism: same method, different behavior
const shapes = [new Circle(5), new Rectangle(4,6)];
shapes.forEach(s => console.log(s.toString()));
// "Area: 78.54"
// "Area: 24.00"

✅ Key Takeaways

  • Classes are blueprints; objects are instances with their own state.
  • Encapsulation bundles data and methods, hiding implementation details.
  • Inheritance lets child classes reuse and extend parent behavior.
  • Polymorphism enables one interface to work across many types — the key to flexible design.
  • Design around what an object does (its interface), not how it does it.
Module 06

Computer Architecture

⏱ ~55 min🟡 Intermediate⚙️ Hardware

Understanding how a CPU actually executes your code — the physical journey from a high-level function call to billions of transistors switching state — transforms you from someone who writes programs into someone who understands them at the deepest level.

CPU Internals

The Central Processing Unit is made of three key components: the Arithmetic Logic Unit (ALU), which performs all math and comparisons; the Control Unit (CU), which orchestrates execution; and registers, the CPU's tiny, ultra-fast local storage (typically 16–32 registers, each 64 bits wide).

🔄
The Fetch-Decode-Execute Cycle

Fetch: load the next instruction from memory into the Instruction Register. Decode: the CU interprets the instruction's opcode. Execute: the ALU or memory system carries out the operation. This cycle runs billions of times per second.

Memory Hierarchy

Memory is arranged in a hierarchy: faster and smaller near the CPU, slower and larger further away. The CPU always tries to find data in the fastest available layer.

LevelSizeSpeedExample
Registers~1 KB< 1 nsCPU internal (rax, rbx…)
L1 Cache32–128 KB~1 nsPer-core, on-chip
L2 Cache256 KB – 4 MB~5 nsPer-core or shared
L3 Cache8–64 MB~20 nsShared across cores
RAM (DRAM)8–128 GB~80 nsMain memory
SSD Storage256 GB–4 TB~100 μsNVMe drive
HDD Storage1–20 TB~5 msSpinning disk

Cache misses are a major performance bottleneck. Writing code that accesses memory sequentially (good spatial locality) keeps data in cache and can be 100× faster than random access patterns.

Assembly Language Primer

Assembly is the human-readable form of machine code. Each assembly instruction maps one-to-one to a CPU instruction. Understanding it demystifies what compiled code actually does.

x86-64 Assembly — C to Assembly
// C code:  int add(int a, int b) { return a + b; }
// Compiles to x86-64 assembly (roughly):

add:
  push   rbp           ; save base pointer
  mov    rbp, rsp      ; set up stack frame
  mov    DWORD [rbp-4], edi  ; store param 'a'
  mov    DWORD [rbp-8], esi  ; store param 'b'
  mov    eax, [rbp-4]   ; load a into register
  add    eax, [rbp-8]   ; add b to a (result in eax)
  pop    rbp           ; restore base pointer
  ret                  ; return (eax holds return value)

Parallelism & Modern CPUs

Modern CPUs improve performance through pipelining (overlapping multiple instruction stages), superscalar execution (multiple ALUs running simultaneously), out-of-order execution (reordering instructions to avoid stalls), and branch prediction (guessing the next instruction path to avoid pipeline flushes).

✅ Key Takeaways

  • The CPU's fetch-decode-execute cycle is the heartbeat of every computation.
  • Memory hierarchy: registers → L1/L2/L3 cache → RAM → disk. Speed drops exponentially.
  • Cache locality is critical — sequential memory access is dramatically faster than random.
  • Assembly shows you the raw instructions your code compiles down to.
  • Modern CPUs use pipelining, out-of-order execution, and branch prediction for speed.
Module 07

Operating Systems

⏱ ~65 min🟡 Intermediate💻 Systems

An Operating System is the master program that manages all hardware resources and provides services to applications. Without an OS, every program would need to directly control the keyboard, screen, disk, and network — a massive, duplicated effort. The OS abstracts hardware into clean, safe interfaces.

Processes & Threads

A process is a running program — it has its own memory space, file handles, and CPU state. A thread is a unit of execution within a process. Multiple threads share the same memory, enabling parallelism within a single application but introducing race conditions and the need for synchronization.

📦
Process
Isolated address space. Crash doesn't affect others. High creation overhead.
🧵
Thread
Shares memory with siblings. Lightweight. Must synchronize access to shared data.
🔒
Mutex
A lock that ensures only one thread accesses a resource at a time.
🚦
Semaphore
Allows N threads through concurrently. Used for resource pools.

CPU Scheduling

On a single CPU, only one thread runs at a time. The scheduler rapidly switches between threads to create the illusion of concurrency. Common algorithms include Round Robin (each process gets equal time slices), Priority Scheduling (high-priority tasks run first), and Completely Fair Scheduler (Linux's approach using a red-black tree).

⚠️
Deadlock

A deadlock occurs when two threads each hold a resource the other needs, and neither can proceed. Prevention requires careful lock ordering or using lock-free data structures.

Memory Management

The OS uses virtual memory to give each process the illusion of having the entire address space to itself. Physical memory is divided into fixed-size pages (typically 4KB). A page table maps each process's virtual addresses to physical ones. If a page isn't in RAM, a page fault triggers loading it from disk.

File Systems

A file system organizes data on storage devices into files and directories. Modern file systems include: NTFS (Windows), ext4 (Linux), APFS (macOS). They handle metadata (permissions, timestamps, sizes), journaling (crash recovery), and block allocation.

System Calls

Programs communicate with the OS through system calls — privileged operations like opening files, allocating memory, or creating processes. User code runs in user mode with restricted privileges; system calls briefly switch to kernel mode where the OS has full hardware access.

Pseudocode — Key System Calls
// File I/O
fd  = open("/etc/hosts", O_RDONLY)   // returns file descriptor
read(fd, buffer, 1024)               // read up to 1024 bytes
write(fd, data, len)
close(fd)

// Process management
pid = fork()   // duplicate current process
exec("/bin/ls", args)  // replace process image
wait(pid)      // wait for child to finish

// Memory
ptr = mmap(NULL, 4096, PROT_READ|PROT_WRITE, ...)
munmap(ptr, 4096)

✅ Key Takeaways

  • The OS manages CPU, memory, file systems, and I/O so programs don't have to.
  • Processes have isolated memory; threads share it — enabling parallelism but requiring synchronization.
  • The scheduler creates the illusion of concurrency on a finite number of CPU cores.
  • Virtual memory gives each process its own address space via page tables.
  • System calls are the gated interface between user programs and the OS kernel.
Module 08

Databases

⏱ ~70 min🟡 Intermediate🗄️ Data

Nearly every application of any significance stores data persistently. Databases are the systems that make data storage, retrieval, and manipulation reliable, concurrent, and efficient. Understanding databases separates a capable developer from a proficient one.

The Relational Model

The relational model (E.F. Codd, 1970) organizes data into tables (relations) of rows and columns. Tables are linked by foreign keys — references to primary keys in other tables. This simple model has proven remarkably powerful for 50+ years.

SQL — Define a Schema
CREATE TABLE users (
  id         INT          PRIMARY KEY AUTO_INCREMENT,
  username   VARCHAR(50)  UNIQUE NOT NULL,
  email      VARCHAR(255) UNIQUE NOT NULL,
  created_at TIMESTAMP    DEFAULT NOW()
);

CREATE TABLE posts (
  id         INT  PRIMARY KEY AUTO_INCREMENT,
  user_id    INT  NOT NULL,
  title      VARCHAR(200),
  body       TEXT,
  FOREIGN KEY (user_id) REFERENCES users(id)
);

SQL Queries

SQL — CRUD Operations
-- CREATE
INSERT INTO users (username, email)
VALUES ('alice', 'alice@example.com');

-- READ with JOIN
SELECT u.username, p.title, p.body
FROM   posts p
JOIN   users u ON p.user_id = u.id
WHERE  u.username = 'alice'
ORDER BY p.id DESC
LIMIT  10;

-- UPDATE
UPDATE users
SET    email = 'newalice@example.com'
WHERE  id = 1;

-- DELETE
DELETE FROM posts WHERE id = 42;

Normalization & Indexes

Normalization is the process of organizing tables to reduce data redundancy. The key normal forms: 1NF (atomic columns), 2NF (no partial dependencies), 3NF (no transitive dependencies). Well-normalized databases are easier to maintain and less prone to inconsistencies.

Indexes are auxiliary data structures (usually B-trees) that make queries faster. Without an index, a query must scan every row (O(n)). With one, it's O(log n). The trade-off: indexes speed up reads but slow down writes and consume storage.

ACID Properties

⚛️
Atomicity
A transaction is all-or-nothing. Bank transfer either moves money in both places or neither.
Consistency
Transactions bring the DB from one valid state to another. No constraint violations.
🔀
Isolation
Concurrent transactions don't interfere with each other.
💾
Durability
Once committed, data survives crashes. Written to persistent storage (WAL).

NoSQL Databases

NoSQL databases sacrifice some ACID guarantees for scalability and flexibility. Types include: Document (MongoDB — JSON-like), Key-Value (Redis — ultra-fast cache), Wide-Column (Cassandra — massive scale), Graph (Neo4j — relationships).

💡
SQL or NoSQL?

Use SQL (relational) when data has clear relationships and you need ACID guarantees. Use NoSQL for massive horizontal scale, flexible schemas, or specific access patterns (graph traversals, time series, caching).

✅ Key Takeaways

  • The relational model (SQL) organizes data into tables connected by foreign keys.
  • SQL's four core operations are SELECT, INSERT, UPDATE, DELETE (CRUD).
  • Normalization reduces redundancy; indexes speed up reads at the cost of slower writes.
  • ACID properties guarantee reliability in concurrent, failure-prone environments.
  • NoSQL trades some guarantees for horizontal scalability and flexible data models.
Module 09

Computer Networks

⏱ ~60 min🟡 Intermediate🌐 Networking

The internet — the largest network ever built — is a layered system of protocols. Understanding networking unlocks how web applications, APIs, security systems, and distributed services actually work beneath every HTTP request you've ever made.

The OSI & TCP/IP Models

Networking is divided into layers, each providing services to the layer above and abstracting the layer below. The OSI model has 7 conceptual layers; the TCP/IP model collapses these into 4 practical layers used in real implementations.

TCP/IP LayerOSI EquivalentProtocol ExamplesResponsibility
Application7-5HTTP, DNS, SMTP, FTPUser-facing protocols
Transport4TCP, UDPEnd-to-end communication, ports
Internet3IP, ICMP, ARPRouting across networks
Link2-1Ethernet, Wi-FiPhysical transmission on local network

TCP vs UDP

TCP (Transmission Control Protocol) provides reliable, ordered, error-checked delivery. It uses a three-way handshake (SYN → SYN-ACK → ACK) to establish a connection, and automatically retransmits lost packets. Used for web, email, file transfer — anything where every byte matters.

UDP (User Datagram Protocol) is connectionless and unreliable — packets may be lost, duplicated, or arrive out of order. But it is much faster. Used for video streaming, gaming, DNS, and VoIP where speed trumps perfect delivery.

IP Addresses & DNS

Every device on the internet has an IP address. IPv4 addresses are 32-bit numbers written as four octets (e.g., 192.168.1.1). IPv6 uses 128-bit addresses to accommodate billions more devices. Subnets divide address spaces into logical groups; NAT allows many devices to share one public IP.

DNS (Domain Name System) is the internet's phonebook: it translates human-readable names (google.com) into IP addresses that routers can use. DNS is hierarchical — root servers, TLD servers (.com, .org), authoritative servers for each domain.

HTTP/HTTPS

HTTP (HyperText Transfer Protocol) is the foundation of the web. It is a request-response protocol: the client sends a request, the server sends a response. HTTP is stateless — each request is independent.

HTTP — Request & Response
── REQUEST ──────────────────────────────
GET /api/users/42 HTTP/1.1
Host: api.example.com
Authorization: Bearer eyJhbGci...
Accept: application/json

── RESPONSE ─────────────────────────────
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: max-age=3600

{
  "id": 42,
  "name": "Alice",
  "email": "alice@example.com"
}

HTTPS wraps HTTP in TLS (Transport Layer Security), encrypting all traffic. A TLS handshake authenticates the server via a certificate and establishes a shared encryption key. The padlock icon in your browser means TLS is in use.

HTTP Status Codes

2xx Success
200 OK · 201 Created · 204 No Content
↪️
3xx Redirect
301 Moved Permanently · 302 Found · 304 Not Modified
⚠️
4xx Client Error
400 Bad Request · 401 Unauthorized · 403 Forbidden · 404 Not Found
🔥
5xx Server Error
500 Internal Server Error · 502 Bad Gateway · 503 Unavailable

✅ Key Takeaways

  • TCP/IP organizes networking into four layers: Application, Transport, Internet, and Link.
  • TCP is reliable and ordered; UDP is fast but lossy — choose based on your use case.
  • IP addresses uniquely identify devices; DNS maps domain names to IPs.
  • HTTP is a stateless, text-based protocol; HTTPS encrypts it using TLS.
  • HTTP status codes indicate success (2xx), redirect (3xx), client error (4xx), server error (5xx).
Module 10

Web Development

⏱ ~75 min🟡 Intermediate🌍 Web

Web development encompasses everything that makes websites and web applications work. It divides into frontend (what the user sees and interacts with) and backend (servers, databases, and logic running behind the scenes). Together they form the full-stack.

The Frontend Trinity

Every webpage is built from three languages that work in concert:

HTML — Structure
<!-- HTML defines the structure (content and semantics) -->
<article class="card">
  <header>
    <h2>Article Title</h2>
    <time datetime="2025-01-01">Jan 1, 2025</time>
  </header>
  <p>Article content goes here.</p>
  <a href="/read-more">Read more</a>
</article>
CSS — Presentation
/* CSS defines how elements look */
.card {
  background: #fff;
  border-radius: 12px;
  padding: 24px;
  box-shadow: 0 2px 12px rgba(0,0,0,.1);
  transition: transform .2s;
}
.card:hover { transform: translateY(-4px); }

/* CSS Grid — modern two-column layout */
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 20px;
}
JavaScript — DOM Manipulation
// JavaScript brings pages to life
const btn   = document.querySelector("#like-btn");
const count = document.querySelector("#like-count");
let likes = 0;

btn.addEventListener("click", () => {
  likes++;
  count.textContent = likes;
  btn.classList.toggle("liked");
});

Frontend Frameworks

For complex, interactive applications, writing raw DOM manipulation becomes unwieldy. Modern frontend frameworks manage UI state and efficiently update only the parts of the DOM that change.

⚛️
React
Component-based UI library by Meta. Virtual DOM, hooks, massive ecosystem.
💚
Vue
Progressive framework. Gentle learning curve, reactive data binding.
🔴
Angular
Full opinionated framework by Google. TypeScript-first, enterprise-oriented.
🔥
Svelte
Compiles away the framework. Zero runtime overhead, built-in reactivity.

Backend Development & REST APIs

The backend handles business logic, database operations, authentication, and serving data to the frontend. A REST API (Representational State Transfer) is the most common style: it uses HTTP methods and URLs to perform CRUD operations on resources.

Node.js / Express — REST API
const express = require("express");
const app     = express();
app.use(express.json());

let todos = [{ id:1, text:"Learn Node", done:false }];

app.get("/todos", (req, res) => {
  res.json(todos);           // GET all
});

app.post("/todos", (req, res) => {
  const todo = { id: Date.now(), ...req.body };
  todos.push(todo);
  res.status(201).json(todo); // POST create
});

app.delete("/todos/:id", (req, res) => {
  todos = todos.filter(t => t.id != req.params.id);
  res.sendStatus(204);       // DELETE
});

app.listen(3000);

✅ Key Takeaways

  • HTML structures content, CSS styles it, JavaScript makes it interactive — they always work together.
  • The DOM is the browser's in-memory model of the page; JavaScript manipulates it in real time.
  • Frontend frameworks (React, Vue, Svelte) manage UI state efficiently through components.
  • REST APIs use HTTP verbs (GET, POST, PUT, DELETE) to perform CRUD on resources.
  • The full stack = frontend (browser) + backend (server) + database (persistence).
Module 11

Software Engineering

⏱ ~65 min🟡 Intermediate🔧 Craft

Writing code that works once is easy. Writing code that is maintainable, testable, and scalable — that can be worked on by a team for years — is the discipline of software engineering. This module covers the practices that separate professionals from amateurs.

Version Control with Git

Git is the version control system used by virtually every software team in the world. It tracks every change to every file, lets multiple developers work in parallel on branches, and merges changes safely. GitHub, GitLab, and Bitbucket host Git repositories remotely.

Git — Essential Commands
# Initialize a new repo
git init

# Stage and commit changes
git add .                         # stage everything
git commit -m "feat: add login page"

# Branching workflow
git checkout -b feature/auth     # create + switch branch
git merge feature/auth           # merge into current branch
git rebase main                  # replay commits on top of main

# Remote operations
git clone https://github.com/user/repo.git
git push origin feature/auth
git pull origin main

# Inspect
git log --oneline --graph --all  # visual branch history
git diff HEAD~1                  # changes since last commit

Testing

Automated testing is the practice of writing code that verifies your code works. Without tests, refactoring is terrifying — any change might break something undetected. The testing pyramid describes three levels:

🧪
Unit Tests
Test individual functions in isolation. Fast, precise, many of them. Jest, Pytest, JUnit.
🔗
Integration Tests
Test how multiple components work together. Slower, fewer. Test the API layer.
🌐
End-to-End Tests
Simulate real user actions in a browser. Slowest, fewest. Cypress, Playwright.
JavaScript — Unit Tests with Jest
// sum.js
function sum(a, b) { return a + b; }
module.exports = sum;

// sum.test.js
const sum = require("./sum");

describe("sum function", () => {
  test("adds two positive numbers", () => {
    expect(sum(1, 2)).toBe(3);
  });
  test("handles negative numbers", () => {
    expect(sum(-1, 5)).toBe(4);
  });
  test("returns 0 for 0 + 0", () => {
    expect(sum(0, 0)).toBe(0);
  });
});

Design Patterns

Design patterns are reusable solutions to commonly occurring design problems. Documented by the "Gang of Four" (GoF) in 1994, they give developers a shared vocabulary. Key patterns:

  • Singleton: Ensures a class has only one instance (e.g., a configuration object or database connection pool).
  • Observer: Objects subscribe to events; the publisher notifies all subscribers when something changes. Foundation of event systems and UI frameworks.
  • Factory: Encapsulates object creation logic so callers don't need to know which specific class to instantiate.
  • Strategy: Defines a family of algorithms and makes them interchangeable at runtime.
  • MVC (Model-View-Controller): Separates data (Model), display (View), and logic (Controller). Used by virtually every web framework.

Agile & Software Development Lifecycle

The Software Development Lifecycle (SDLC) encompasses requirements → design → implementation → testing → deployment → maintenance. Agile is a family of iterative methodologies that favors short development cycles ("sprints"), continuous feedback, and adapting to change over rigid upfront planning. Scrum is the most popular Agile framework.

✅ Key Takeaways

  • Git tracks every change; branching enables parallel development without conflict.
  • Automated tests are safety nets — write them especially before refactoring.
  • The testing pyramid: many unit tests, fewer integration tests, minimal E2E tests.
  • Design patterns are proven solutions; knowing them avoids reinventing the wheel.
  • Agile iterates quickly — ship small, learn fast, adapt continuously.
Module 12

Theory of Computation

⏱ ~70 min🔴 Advanced🧠 Theory

Theory of Computation asks: What are the fundamental limits of what computers can do? This is pure mathematics applied to machines. Grasping these ideas separates those who use computer science from those who truly understand it.

Formal Languages & Automata

A formal language is a set of strings over some alphabet, defined by rules. Automata are abstract machines that recognize languages. The hierarchy of languages and their corresponding machines is the Chomsky hierarchy:

Language TypeMachineExample
RegularFinite Automaton (DFA/NFA)Simple patterns, lexer tokens
Context-FreePushdown AutomatonProgramming language grammars
Context-SensitiveLinear Bounded AutomatonNatural language (roughly)
Recursively EnumerableTuring MachineAny computable problem

Regular Expressions

Regular expressions (regex) define regular languages — the simplest class. They are implemented by compiling to a DFA. Every regex engine you've used is, at its core, an automaton.

Regex Patterns
// Regex syntax (used in most languages)
/^\d+$/          // one or more digits, entire string
/^[a-zA-Z]{3,}$/ // 3+ letters only
/\b\w+@\w+\.\w+\b/  // crude email pattern
/https?:\/\/.+/ // URL starting with http or https

// In JavaScript:
const emailRe = /^[\w.-]+@[\w.-]+\.[a-z]{2,}$/i;
emailRe.test("user@example.com"); // true
emailRe.test("notanemail");       // false

// Regex CANNOT match nested structures like ((())) — need CFG for that

The Turing Machine

A Turing Machine (Alan Turing, 1936) is an abstract machine with an infinite tape, a read/write head, a finite set of states, and a transition table. It can compute anything a modern computer can compute — they are computationally equivalent. The Turing Machine defines the outer boundary of what is computable.

Church-Turing Thesis

Any function that is "effectively computable" by any physical process can be computed by a Turing Machine. This is not a theorem — it cannot be proved — but it is universally accepted. It means the limits of the Turing Machine are the limits of all possible computers.

Decidability & the Halting Problem

A problem is decidable if there exists a Turing Machine that always halts and gives the correct yes/no answer for any input. The Halting Problem (does a given program halt on a given input?) is undecidable — Turing proved no algorithm can solve it in general. This is a fundamental limit of computation, not of current technology.

Complexity Theory: P vs NP

P (polynomial time) is the class of problems solvable in O(n^k) time — "efficiently solvable." NP (nondeterministic polynomial) is the class of problems where a given solution can be verified in polynomial time — though finding the solution may be hard. The P vs NP question asks: is every problem whose solution is easily verifiable also easily solvable? It is the most famous unsolved problem in mathematics and CS.

P
Sorting, shortest path, primality test. Efficiently solvable.
🧩
NP
Sudoku, graph coloring, subset sum. Easy to verify; may be hard to solve.
🔒
NP-Complete
Hardest problems in NP. If any P = NP, all NP-complete become polynomial.
♾️
NP-Hard
At least as hard as NP-complete. May not even be in NP.

Most cryptographic security (RSA, elliptic curves) relies on the assumption that certain NP problems (factoring large integers) are not in P. If P = NP, modern encryption would collapse.

✅ Key Takeaways

  • The Chomsky hierarchy classifies languages by complexity: regular → context-free → Turing-recognizable.
  • Regular expressions match regular languages and compile down to finite automata.
  • Turing Machines define the limits of computation — any physical computer is equivalent.
  • The Halting Problem is provably undecidable — no algorithm can solve it for all inputs.
  • P vs NP is unsolved; most cryptography depends on NP-hard problems being intractable.
Module 13

Artificial Intelligence & Machine Learning

⏱ ~80 min🔴 Advanced🤖 AI

Artificial Intelligence has moved from science fiction to the engine of the modern economy. Machine Learning — the subset of AI where systems learn from data rather than explicit rules — now powers recommendation systems, language models, autonomous vehicles, medical diagnosis, and much more.

Types of Machine Learning

🏷️
Supervised Learning
Train on labeled data (input → known output). Classification, regression. Most common type.
🔍
Unsupervised Learning
Find patterns in unlabeled data. Clustering (k-means), dimensionality reduction (PCA).
🎮
Reinforcement Learning
Agent learns by trial-and-error to maximize reward. AlphaGo, game-playing AI, robotics.
🌀
Self-Supervised
Labels derived from data itself. How LLMs are pretrained — predict the next token.

Linear Regression: The Foundation

The simplest ML model is linear regression — fitting a line through data points. Despite its simplicity, it encapsulates the fundamental ML loop: define a model, a loss function, and an optimization algorithm.

Python — Linear Regression (from scratch)
import numpy as np

# Dataset: hours studied → exam score
X = np.array([1, 2, 3, 4, 5])
y = np.array([55, 60, 70, 75, 85])

# Model: y_hat = w * x + b
w, b = 0.0, 0.0
lr   = 0.01   # learning rate
n    = len(X)

for epoch in range(1000):
  y_hat = w * X + b          # forward pass
  error = y_hat - y          # residuals
  loss  = (error**2).mean()   # mean squared error
  # gradients (calculus)
  dw = (2/n) * (error * X).sum()
  db = (2/n) * error.sum()
  # gradient descent update
  w -= lr * dw
  b -= lr * db

print(f"w={w:.2f}, b={b:.2f}")  # w≈6.0, b≈48.0

Neural Networks

A neural network is a chain of layers, each containing neurons. Each neuron computes a weighted sum of its inputs and applies a nonlinear activation function. By stacking many layers, networks can approximate arbitrarily complex functions — this is the universal approximation theorem.

Training works via backpropagation: compute the loss on the output, calculate gradients using the chain rule (calculus), and update each weight in the direction that reduces the loss. Repeat for thousands of iterations until the network performs well.

Python — Neural Net Concept (PyTorch)
import torch
import torch.nn as nn

# A simple feed-forward network
model = nn.Sequential(
  nn.Linear(784, 256),   # input layer  (28×28 pixel image)
  nn.ReLU(),              # activation function
  nn.Linear(256, 128),   # hidden layer
  nn.ReLU(),
  nn.Linear(128, 10),    # output layer (10 digit classes)
)

optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)
loss_fn   = nn.CrossEntropyLoss()

for x, y in dataloader:
  pred  = model(x)           # forward pass
  loss  = loss_fn(pred, y)   # compute error
  loss.backward()             # backpropagate gradients
  optimizer.step()           # update weights
  optimizer.zero_grad()      # clear gradients for next batch

Deep Learning & Modern AI

Deep learning refers to networks with many layers (dozens to thousands). Breakthroughs include CNNs (Convolutional Neural Networks, for images), RNNs (Recurrent Networks, for sequences), and Transformers (2017, "Attention Is All You Need") — the architecture behind every large language model (GPT-4, Claude, Gemini).

Modern AI systems are trained on enormous datasets and compute, then fine-tuned and aligned to specific tasks using techniques like RLHF (Reinforcement Learning from Human Feedback).

✅ Key Takeaways

  • ML learns from data; the three main paradigms are supervised, unsupervised, and reinforcement learning.
  • Every ML model involves: architecture (structure), loss function (error measure), optimizer (training algorithm).
  • Neural networks stack layers of weighted transformations with nonlinear activations.
  • Backpropagation uses calculus (chain rule) to compute gradients and update weights.
  • Transformers and attention mechanisms power all modern large language models.
Module 14

Cybersecurity

⏱ ~65 min🔴 Advanced🔒 Security

Every system connected to a network is a potential target. Security is not a feature you add at the end — it is a discipline woven through every layer of software and infrastructure. This module introduces the principles, attacks, and defenses every developer must understand.

The CIA Triad

🔒
Confidentiality
Data is accessible only to authorized parties. Encryption, access control.
Integrity
Data has not been tampered with. Hashes, digital signatures, checksums.
Availability
Systems are accessible when needed. Redundancy, DDoS protection, backups.

Cryptography

Symmetric encryption uses the same key to encrypt and decrypt (AES-256). It's fast but requires securely sharing the key. Asymmetric encryption uses a public/private key pair: anything encrypted with the public key can only be decrypted with the private key (RSA, ECC). HTTPS uses asymmetric crypto to exchange a symmetric key, then switches to symmetric for speed.

Hashing transforms input into a fixed-length, irreversible digest. SHA-256 produces a 256-bit hash. Even a single changed character produces a completely different hash. Used for password storage (with salting) and data integrity.

JavaScript — Cryptography Concepts
// Password hashing (Node.js with bcrypt)
const bcrypt = require("bcrypt");

// Storing a password — NEVER store plaintext
const hash = await bcrypt.hash("user_password", 12);
// "$2b$12$X7hVkRq3…" (salt is embedded in hash)

// Verifying a password on login
const ok = await bcrypt.compare("user_password", hash);

// JWT (JSON Web Token) — stateless auth
const jwt = require("jsonwebtoken");
const token = jwt.sign({ userId: 42 }, process.env.SECRET, { expiresIn: "24h" });
const payload = jwt.verify(token, process.env.SECRET);

Common Attacks

Knowing how attacks work is the first step to preventing them. The OWASP Top 10 lists the most critical web security risks:

SQL Injection — Attack & Defense
// ❌ VULNERABLE — user input directly in query string
const query = `SELECT * FROM users WHERE email='${req.body.email}'`;
// Attacker inputs: ' OR '1'='1  → returns ALL users!

// ✅ SAFE — parameterized queries (the only correct approach)
const user = await db.query(
  "SELECT * FROM users WHERE email = $1",
  [req.body.email]   // driver escapes it automatically
);

// XSS (Cross-Site Scripting) — sanitize all user output
// ❌ Vulnerable: element.innerHTML = userInput
// ✅ Safe:       element.textContent = userInput
AttackDescriptionDefense
SQL InjectionMalicious SQL in user inputParameterized queries / ORMs
XSSInjecting scripts into web pagesOutput encoding, CSP headers
CSRFForged requests from another siteCSRF tokens, SameSite cookies
PhishingTricking users into revealing credentialsMFA, security training
DDoSFlooding a server with trafficRate limiting, CDN, WAF
Broken AuthWeak passwords, session theftMFA, secure sessions, bcrypt

Security Principles & Best Practices

  • Principle of Least Privilege: Every component should have only the permissions it strictly needs.
  • Defense in Depth: Layer multiple controls so a single failure doesn't compromise the system.
  • Secure by Default: Default configurations should be the most secure, not the most convenient.
  • Never Trust User Input: Validate and sanitize everything arriving from outside your system.
  • Keep Secrets Secret: API keys, passwords, and tokens live in environment variables or secret managers — never in source code.
  • Update Dependencies: Most breaches exploit known vulnerabilities in outdated libraries.
🔑
Authentication vs Authorization

Authentication verifies who you are (login). Authorization verifies what you're allowed to do (permissions). Both must be enforced on the server — never trust the client to enforce either.

🎓 Curriculum Complete!

  • The CIA triad (Confidentiality, Integrity, Availability) is the foundation of all security thinking.
  • Asymmetric cryptography enables HTTPS; symmetric crypto provides fast bulk encryption.
  • SQL injection is prevented exclusively by parameterized queries — string concatenation is never safe.
  • XSS is prevented by encoding output; CSRF by tokens and SameSite cookie policy.
  • Least privilege, defense in depth, and secure-by-default are the core architectural principles.